-->
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.  [ 5 posts ] 
Author Message
 Post subject: entities of oneToMany relations multiply after "refresh
PostPosted: Wed Apr 05, 2006 7:04 pm 
Newbie

Joined: Tue Mar 28, 2006 4:03 pm
Posts: 11
Please have a look at this, i think this is a major bug...

Parent has two oneToMany relations and the "hibernate.max_fetch_depth"is the default, so upon doing "entitymanager.refresh(parent)" everything is loaded by a big "left outer join xxx left outer join yyy":

Code:
select parent0_.id as id157_2_, children1_.parent_id as parent2_4_,
   children1_.id as id4_, children1_.id as id158_0_, children1_.parent_id as parent2_158_0_,
   kinder2_.parent_id as parent2_5_, kinder2_.id as id5_, kinder2_.id as id159_1_, kinder2_.parent_id as parent2_159_1_
   from FOOBAR_PARENT parent0_
   left outer join FOOBAR_CHILD children1_ on parent0_.id=children1_.parent_id
   left outer join FOOBAR_KIND kinder2_ on parent0_.id=kinder2_.parent_id
   where parent0_.id=?


which obiously produces a lot more then it should in case one of the two relations has more then one entry.

As a workaround i now set "hibernate.max_fetch_depth=0" and the problem disapperas.

to reproduce:

Code:
Parent parent = new Parent();
   
    List<Child> children = new ArrayList<Child>();
   
    Child child = new Child();
    child.setParent(parent);
    children.add(child);
   
    child = new Child();
    child.setParent(parent);
    children.add(child);

    parent.setChildren(children);
   
    List<Kind> kinder = new ArrayList<Kind>();
   
    Kind kind = new Kind();
    kind.setParent(parent);
    kinder.add(kind);

    kind = new Kind();
    kind.setParent(parent);
    kinder.add(kind);
   
    parent.setKinder(kinder);
   
    manager.persist(parent);
    manager.flush();
   
    int numChildrenBeforeRefresh = parent.getChildren().size();
   
    manager.refresh(parent);
    int numChildrenAfterRefresh = parent.getChildren().size();
   
    if (numChildrenBeforeRefresh!=numChildrenAfterRefresh) {
      System.out.println("Error. Number of children magically changed...");
    }


Parent:

Code:
@Entity
@Table(name = "FOOBAR_PARENT")
public class Parent implements java.io.Serializable {

  protected long id;

  protected List<Child> children;

  protected List<Kind> kinder;

  @Id
  @GeneratedValue
  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
  public List<Child> getChildren() {
    return children;
  }

  public void setChildren(List<Child> children) {
    this.children = children;
  }

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
  public List<Kind> getKinder() {
    return kinder;
  }

  public void setKinder(List<Kind> kinder) {
    this.kinder = kinder;
  }

}


Child
Code:
@Entity
@Table(name = "FOOBAR_CHILD")
public class Child implements java.io.Serializable {

  protected long id;

  protected Parent parent;

  @Id
  @GeneratedValue
  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "parent_id")
  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }

}


Kind
Code:
@Entity
@Table(name = "FOOBAR_KIND")
public class Kind implements java.io.Serializable {

  protected long id;



  protected Parent parent;

  @Id
  @GeneratedValue
  public long getId() {
    return id;
  }

  public void setId(long id) {
    this.id = id;
  }



  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "parent_id")
  public Parent getParent() {
    return parent;
  }

  public void setParent(Parent parent) {
    this.parent = parent;
  }

}


My Versions:

* JBoss 4.0.4RC1
* Hibernate Annotations 3.1beta8
* Hibernate EntityManager 3.1beta6
* Firebird 1.5[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 05, 2006 7:09 pm 
Newbie

Joined: Tue Mar 28, 2006 4:03 pm
Posts: 11
...and the same problem of course happens if i set the relations to "EAGER" loading and just load the "parent in another session/transaction. The sql looks the same and the relations have duplicates....


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 06, 2006 11:32 am 
Beginner
Beginner

Joined: Mon Sep 12, 2005 3:27 am
Posts: 48
Don't use <List>. Instead use <Set>. Lists allow duplicate entries, Set doesn't ...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 8:49 am 
Newbie

Joined: Tue Mar 28, 2006 4:03 pm
Posts: 11
Rhoadan,

thanks for your reply.

the key statement in the doc is indeed:

Quote:
[2.2.5.3.1] So specifically, java.util.List collections wo @OrderBy nor @org.hibernate.annotations.IndexColumn are going to be considered as bags.


I consider this as a common pitfall for developers, so maybe hibernate should at least log a warning in case a relation is a mapped as a List without having an @OrderBy or @IndexColumn

But anyway, there still is another issue with @OrderBy, i opened a separate Thread for that:

http://forum.hibernate.org/viewtopic.php?t=957848


Top
 Profile  
 
 Post subject:
PostPosted: Sun Apr 16, 2006 11:58 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1413

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.