926 words

find() delay

#1
2011-05-23 09:54

Hi, I tried objectdb in following steps:

1, for 1 to 30 {trans.begin(); create typeC o; em.persist(o); trans.commit();}

2, for 1 to 30 {p = em.find(typeC.class, i); print(p)}

So simple a test, there is no result in one go; I have to disable step 1 and run again, then Step 2 output the expected results.

I tried em.flush(), em.clear(), etc.. that do not work.

Any idea? TIA

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #11
#2
2011-05-23 15:35

Maybe trans is not a transaction of em.

Maybe different EntityManager instances are used and the L2 cache is enabled.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #283
#3
2011-05-23 17:39

L2 cache? I'm not sure. But why the second find() will output?

By the way, a query "select e from nodes e" will be ok regardless of the first time or the second time.

My codes, again, are similar to these:

1. trans = em.getTransaction(); trans.begin(); create typeC o; em.persist(o); trans.commit();

2. Query q =  em.createQuery("select e from typeC e"); List l = q.getResultList(); // this works

3. typeC p = em.find(typeC.class, i);  // this p will be null

I'm doubting the example in jpab.jar runs twice in each test and choose only the second result, maybe is related to this.

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #12
#4
2011-05-23 18:23

The following program demonstrates how it works:

import javax.persistence.*;
 
public final class Test {
    public static void main(String[] args){
 
        EntityManagerFactory emf = Persistence.createEntityManagerFactory(
            "$objectdb/db/test.odb");
        EntityManager em = emf.createEntityManager();
 
        for (int i = 0; i < 30; i++) {
            em.getTransaction().begin();
            em.persist(new MyEntity());
            em.getTransaction().commit();
        }
 
        for (int i = 0; i < 30; i++) {
            System.out.println(em.find(MyEntity.class, i));
        }
        em.close();
        emf.close();
    }
 
    @Entity
    public static final class MyEntity {
        @Id @GeneratedValue long id;
    }
}

Try to change this example to demonstrate the issue that you have.

Please try to generate a simple test like the one above for any other problem that you may have. Otherwise it is very difficult to understand the problem and provide help.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #284
#5
2011-05-24 01:23

Ok, the minimal codes are here:

public final class Test {
 public static void main(String[] args){
 
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("$objectdb/db/test.odb");
  EntityManager em = emf.createEntityManager();
  EntityTransaction trans = em.getTransaction();
  int iBlock = 3;
  //* codes-1
  for (int i = 1; i <= 3*iBlock; i++) {
   trans.begin();
   Node o = new Node();
   Node p = em.find(Node.class, i/3);
   if (null==p) System.out.printf("Node %d has no parent.%n", i);
   o.setParent( p );
   em.persist(o);
   trans.commit();
  }//*/
 
  /* codes-2.
  em.close();
  em = emf.createEntityManager();
  //*/
  em.clear(); // codes-3
  trans = em.getTransaction();
  int iSum = 0;
  for (int i=1;i<=3*iBlock;i++){
   Node o = em.find(Node.class, i);
   if (null== o){
    System.out.printf("%s is not Node %n", o);
    continue;
   }
   List<Node> sons = o.getSons();
   if (null==sons){
    System.out.printf("%s has no sons %n", sons);
    continue;
   }
   int iCnt = sons.size();
   System.out.printf("%d : type:Node, sons:%d %n",i, iCnt);
   iSum += iCnt;
   Iterator<Node> it = sons.iterator();
   while (it.hasNext()){
    Node en = it.next();
    System.out.printf("child : %d %n", en.getId());
   }
  }
  System.out.printf("The sum : %d %n", iSum);
  em.close();
  emf.close();
 }
 @Entity
 static class Node {
  @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
  private int id;
  @ManyToOne @JoinColumn(name="pid")
  protected Node parent;
 
  @OneToMany(mappedBy="parent",fetch=FetchType.EAGER)
  protected List<Node> Sons;
 
  public int getId() {
   return id;
  }
  public Node getParent() {
   return parent;
  }
 
  public List<Node> getSons() {
   return Sons;
  }
 
  public void setParent(Node parent) {
   this.parent = parent;
  }
 }
}

The ideal result is here:

Node 1 has no parent.
Node 2 has no parent.
1 : type:Node, sons:3
child : 3
child : 4
child : 5
2 : type:Node, sons:3
child : 6
child : 7
child : 8
3 : type:Node, sons:1
child : 9
4 : type:Node, sons:0
5 : type:Node, sons:0
6 : type:Node, sons:0
7 : type:Node, sons:0
8 : type:Node, sons:0
9 : type:Node, sons:0
The sum : 7 

The bad result is here:

Node 1 has no parent.
Node 2 has no parent.
null has no sons
null has no sons
null has no sons
null has no sons
null has no sons
null has no sons
null has no sons
null has no sons
null has no sons
The sum : 0 

I tried the "codes-2" or "codes-3", they work with "codes-1" to output the ideal result.

Only "codes-1" will output the bad result.

When the "codes-1" is comment in the second run, the ideal result appears.

So, is there any reasonable method than .clear()?

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #13
#6
2011-05-24 19:17

OK. Now I see the problem.

You have a bidirectional relationship but you update only one side.

It is the application responsibility to update both sides. Otherwise the "mapped by" side will only be available when the object that contains that "mapped by" (inverse) field is retrieved from the database again (as done by "codes-2" and "codes-3").

Please see the documentation on inverse fields and also this forum thread.

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #285
#7
2011-05-24 23:15

Thanks for you hints.

I read this forum thread and find the active method you mentioned. If I have to maintain the inverse fields, then is there a conflict between manual and auto relations? Suppose the Employee and the address are all regular classes, I changed the codes you given in Eml's post:

  em.getTransaction().begin();
 
  Employee employee = new Employee();
  employee.name = "Employee1";
  employee.addresses = new ArrayList<Address>();
 
  Address address1 = new Address();
  address1.line = "address1";
  address1.employee = employee;
  em.persist(address1);                    // changed
  employee.addresses.add(address1);
 
  Address address2 = new Address();
  address2.line = "address2";
  address2.employee = employee;
  em.persist(address2);                    // changed
  // employee.addresses.add(address2);     // changed
 
  em.persist(employee);
  em.getTransaction().commit();

My address List only add once, but the class Address exactly have two many2one relations to the same employee. When the third application visit the data, how many addresses for the employee?

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #14
#8
2011-05-24 23:33

employee.addresses will have exactly the Address instances that you added to it manually - until it is retrieved from the database (e.g. using another EntityManager, after clear, etc.) and then the automatic inverse query is run and the list is built according to the owner side (address.employee).

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #290
#9
2011-05-25 02:44

Thanks.

If there is a large number of objects in cache, the List.add() make sons for a node, how to make it appear in database instancely without clear() or destroying the cache?

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #17
#10
2011-05-25 03:11

Try: em.refresh(employee);

ObjectDB Support
ObjectDB - Fast Object Database for Java (JPA/JDO)
support
support's picture
Joined on 2010-05-03
User Post #297
#11
2011-05-25 03:46

Ok, finally, the refresh() is the bingo.

Thanks very much!

Institute of Computer Technologies
gzdillon
gzdillon's picture
Joined on 2011-05-17
User Post #18

Post Reply

Please read carefully the posting instructions - before posting to the ObjectDB website.

  • You may have to disable pop up blocking in order to use the toolbar (e.g. in Chrome).
  • Use ctrl + right click to open the browser context menu in the editing area (e.g. for using a browser spell checker).
  • To insert formatted lines (e.g. Java code, stack trace) - select a style in the toolbar and then insert the text in the new created block.
  • Avoid overflow of published source code examples by breaking long lines.
  • You may mark in paragraph code words (e.g. class names) with the code style (can be applied by ctrl + D).
  • Long stack traces (> 50 lines) and complex source examples (> 100 lines) should be posted as attachments.
Attachments:
Maximum file size: 32 MB
Cancel