-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Mapping a bidirectional list not working as documented?
PostPosted: Mon Feb 02, 2009 7:44 pm 
Newbie

Joined: Thu Jan 25, 2007 12:32 pm
Posts: 6
I don't understand the behavior of Hibernate when mapping a bidirectional list. The SQL statements that Hibernate produces seem not optimal to me. Can somebody enlighten me?

The scenario is the following: I have a one-to-many parent-child relationship. I map this relationship with a bidirectional list.

According to the Hibernate Annotation Reference Guide (Chapter 2.4.6.2.3. Bidirectional association with indexed collections) the mapping should look like this:

Code:
@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

   ...


Code:
@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

   ...


But in this case Hibernate produces three SQL statements when persisting a parent with one child:

Code:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
Hibernate: update Child set parent_id=?, parent_index=? where id=?

The third statement seems to be redundant, because parent_id and parent_index seem to be set already in the second statement.

When I change the mapping and repeat the attributes 'updatable = false, insertable = false' to the declaration of the @JoinColumn in the Parent like this:

Code:
@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

   ...

Code:
@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

   ...


...then Hibernate seems to produce much more optimized SQL:

Code:
Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)


The client code looks like this:

Code:
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Parent newParent = new Parent();
        newParent.setName("Parent1");

        Child newChild = new Child();
        newChild.setName("Child1");

        newParent.getChildren().add(newChild);
        newChild.setParent(newParent);

        em.persist(newParent);

        em.flush();
        tx.commit();


I am using hibernate-entitymanager 3.4.0.GA.


What am I missing? Is the Hibernate Reference Guide not correct, or am I overlooking something?


Last edited by jbandi on Tue Feb 03, 2009 7:34 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 03, 2009 4:30 am 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
I think your code is okay, you are not missing anything.

You could map the Child as the owner of the association. This is the recommended approach for bidirectional oneToManies. That way you could also spare the extra update.

_________________
-----------------
Need advanced help? http://www.viada.eu


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 03, 2009 6:09 am 
Newbie

Joined: Thu Jan 25, 2007 12:32 pm
Posts: 6
As far as I understand, I CAN'T map the Child as the owner of the association when mapping the association as a LIST.

See Hibernate Documentation:
- Chapter 2.4.6.2.3 in Hibernate Annotations Reference Guide
- Chapter 6.3.3 in Hibernate Reference Guide
- Wiki

The problem is that the index is only known on the Parent side of the relation...

But my assumption is that the documentation, at least the Chapter 2.4.6.2.3 in Hibernate Annotations Reference Guide seems not to be correct, at least not optimal ... thats the point of the code examples in my first post.

Can anybody confirm or refute this?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 06, 2009 2:27 pm 
Newbie

Joined: Thu Jan 25, 2007 12:32 pm
Posts: 6
Ok, I was not reading the Annotations Reference Guide thoroughly enough.

In Chapter 2.2.5.3.2.1 it is stated clearly:

Quote:
To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is obviously not optimized and will produce some additional UPDATE statements.


It probably would not hurt to repeat this information in Chapter 2.4.6.2.3.

Now the question remains: if I repeat the @JoinColumn attributes 'updatable = false' and 'insertable = false' on the Parent (see code in first post) the additional update statements seem not to get produced... is this a legitimate workaround? Or does this result in another problem?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.