-->
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.  [ 1 post ] 
Author Message
 Post subject: Eager fetches (joins) in lazy fetched collection members
PostPosted: Fri Mar 07, 2014 12:10 am 
Newbie

Joined: Fri Dec 03, 2010 10:54 am
Posts: 2
Hi everybody,

i simplified a part of our application (using Hibernate 4.1.5) to explain the problem...
We have a class Entity1 containing a lazy collection (ManyToMany) of class Entity2, which itself contains an eager collection (ManyToMany) of class Entity3 (see below). But if we execute the following code (loading Entity1 with id 1 and traversing it)...

Code:
if (entityManager.isOpen()) {
   Entity1 entity1 = entityManager.find(Entity1.class, new Long(1));
   Set<Entity2> ent2s = entity1.getEntity2s();
   Iterator<Entity2> iter = ent2s.iterator();
   ...
}


...we get the following SQL statements in the log:

Code:
00:57:14,717 DEBUG [org.hibernate.SQL] (ajp--127.0.0.1-8009-1)
    select
        entity1x0_.id as id23_0_,
        entity1x0_.name as name23_0_
    from
        entities.entity1 entity1x0_
    where
        entity1x0_.id=?
00:57:17,971 DEBUG [org.hibernate.SQL] (ajp--127.0.0.1-8009-1)
    select
        entity2s0_.ent1_id as ent1_23_1_,
        entity2s0_.ent2_id as ent2_1_,
        entity2x1_.id as id17_0_,
        entity2x1_.name as name17_0_
    from
        entities.ent1_ent2 entity2s0_
    inner join
        entities.entity2 entity2x1_
            on entity2s0_.ent2_id=entity2x1_.id
    where
        entity2s0_.ent1_id=?
    order by
        entity2x1_.sortorder
00:57:18,081 DEBUG [org.hibernate.SQL] (ajp--127.0.0.1-8009-1)
    select
        entity3s0_.ent2_id as ent1_17_1_,
        entity3s0_.ent3_id as ent2_1_,
        entity3x1_.id as id28_0_,
        entity3x1_.name as name28_0_
    from
        entities.ent2_ent3 entity3s0_
    inner join
        entities.entity3 entity3x1_
            on entity3s0_.ent3_id=entity3x1_.id
    where
        entity3s0_.ent2_id in (
            ?, ?
        )


So it seems that the join fetch definition on Entity2 is ignored and a third statement is generated. I would rather have expected the first statement and ONE additional statement like this:

Code:
    select
        entity2s0_.ent1_id as ent1_421_4_,
        entity2x1_.id as ent2_4_,
        entity2x1_.id as id427_0_,
        entity2x1_.name as name427_0_,
        entity3s0_.ent2_id as ent1_427_5_,
        entity3x1_.id as ent2_5_,
        entity3x1_.id as id429_1_,
        entity3x1_.name as name429_1_
    from
        entities.pp_ent1_ent2 entity2s0_
    left outer join
        entities.pp_entity2 entity2x1_
            on entity2s0_.ent2_id=entity2x1_.id
    left outer join
        entities.pp_ent2_ent3 entity3s0_
            on entity2x1_.id=entity3s0_.ent2_id
    left outer join
        entities.pp_entity3 entity3x1_
            on entity3s0_.ent3_id=entity3x1_.id
    where
        entity2s0_.ent1_id=?


I know there is a Hibernate property max_fetch_depth but the documentation says it only influences single-ended (...ToOne) associations, and tests prove it. So does anybody have an idea why the FetchMode.JOIN is ignored and if there is a way it is not?

Thanks in advance,
best regards
Flo

Code:
@Entity
@Table(name = "entity1", catalog = "entities")
public class Entity1 implements java.io.Serializable {
   private Long id;
   private String name;
   private Set<Entity2> entity2s = new HashSet<Entity2>(0);

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Long getId() {
      return this.id;
   }

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

   @ManyToMany(fetch = FetchType.LAZY, cascade={CascadeType.PERSIST})
   @Fetch(FetchMode.SELECT)
   @BatchSize(size = 100)
   @JoinTable(name = "ent1_ent2", catalog = "entities", joinColumns = { @JoinColumn(name = "ent1_id", referencedColumnName = "id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "ent2_id", referencedColumnName = "id", nullable = false, updatable = false) })
   @OrderBy(value = "sortorder")
   public Set<Entity2> getEntity2s() {
      return this.entity2s;
   }

   public void setEntity2s(Set<Entity2> entity2s) {
      this.entity2s = entity2s;
   }

   @Column(name = "name", nullable = false, length = 30)
   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
   }

}


@Entity
@Table(name = "entity2", catalog = "entities")
public class Entity2 implements java.io.Serializable {
   private Long id;
   private String name;
   private Set<Entity3> entity3s = new HashSet<Entity3>(0);

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Long getId() {
      return this.id;
   }

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

   @ManyToMany(fetch = FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE})
   @Fetch(FetchMode.JOIN)
   @JoinTable(name = "ent2_ent3", catalog = "entities", joinColumns = { @JoinColumn(name = "ent2_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "ent3_id", nullable = false, updatable = false) })
   public Set<Entity3> getEntity3s() {
      return this.entity3s;
   }

   public void setEntity3s(Set<Entity3> entity3s) {
      this.entity3s = entity3s;
   }

   @Column(name = "name", nullable = false, length = 30)
   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
   }

}


@Entity
@Table(name = "entity3", catalog = "entities")
public class Entity3 {
   private Long id;
   private String name;

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id", unique = true, nullable = false)
   public Long getId() {
      return this.id;
   }

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

   @Column(name = "name", nullable = false, length = 30)
   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
   }

}


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

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.