0

I use open JDK 11, JPA 2.1 and Hibernate Core 5.4.0.Final. I have an entity Ave that has many child associations, among which Bid and Buyer. The cardinality is:

1 Ave : Many Bid

1 Ave : Many Buyer

This is an excerpt of the source code of Ave entity:

@Entity
@Table(name = "ave")
@Access(AccessType.FIELD)
public class Ave implements Serializable, SearchableEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", updatable = false, nullable = false)
private int id;


@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE, targetEntity = Buyer.class)
@JoinColumn(name = "ave_id")
@Fetch(value = FetchMode.JOIN)
private Set<Buyer> allPotentialBuyers = new LinkedHashSet<>();


@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = Bid.class)
@JoinColumn(name = "ave_id")

@Fetch(value = FetchMode.JOIN)
private Set<Bid> bids = new HashSet<>();

// ... more code here ....

}

When I execute the JPA query

    Query query2 = this.em.createQuery(" select ave from Ave ave where ave.id =16 ");
    query2.getResultList();

hibernate performs 3 (three) SQL queries, although I do not wish to fetch neither the associated Bid nor Buyer:

1.) FIRST Query - fetch the Ave entities - OK:

04:34:15,717 INFO  [stdout] (default task-2) Hibernate: select ave0_.id as id1_0_, ave0_.angebotType as angebotT2_0_, ave0_.bidStep as bidStep3_0_, ave0_.bidwinner_id as bidwinne7_0_, ave0_.endDate as endDate4_0_, ave0_.home_id as home_id8_0_, ave0_.user_id as user_id5_0_, ave0_.startDate as startDat6_0_, ave0_.vertragsErrichter_id as vertrags9_0_ from ave ave0_ where ave0_.id=16

2.) Secodn query - fetches the associated Bids - why? I DO NOT want!:

04:34:15,928 INFO  [stdout] (default task-2) Hibernate: select bids0_.ave_id as ave_id3_4_0_, bids0_.id as id1_4_0_, bids0_.id as id1_4_1_, bids0_.abgabeDatum as abgabeDa2_4_1_, bids0_.ave_id as ave_id3_4_1_, bids0_.bidmaker_id as bidmaker6_4_1_, bids0_.bidPrice as bidPrice4_4_1_, bids0_.status as status5_4_1_, bids0_.vtgerrichter_id as vtgerric7_4_1_ from bid bids0_ where bids0_.ave_id=?

3.) Third query - fetches the associated Buyers - why? I DO NOT want:

04:34:16,082 INFO  [stdout] (default task-2) Hibernate: select allpotenti0_.ave_id as ave_id2_5_0_, allpotenti0_.id as id1_5_0_, allpotenti0_.id as id1_5_1_, allpotenti0_.ave_id as ave_id2_5_1_, allpotenti0_.contact_id as contact_3_5_1_, allpotenti0_.idx as idx4_5_1_, allpotenti0_.main_buyer_id as main_buy5_5_1_ from buyer allpotenti0_ where allpotenti0_.ave_id=?
Alex Mi
  • 1,409
  • 2
  • 21
  • 35
  • 1
    You tag the question with both jpa 2.0 and 2.2. Tagging with a specific version implies you are asking about a feature that is new in a specific version. Using two versions is weird than, even more since you state in your first paragraph that you use jpa 2.1. Please correct that. And did the answer solve your problem? – Kukeltje Jun 03 '20 at 18:29
  • @Kukeltje I removed the version information from my tags and marked the answer as both helpful and checked, as it directly refers the place in the documentation, where the behaviuor is explained – Alex Mi Jun 04 '20 at 06:05

1 Answers1

2
  1. Hibernate 5.3 + is JPA 2.2 standard.
  2. Your Fetch strategy - @Fetch(FetchMode.JOIN) overrides the FetchType.LAZY you defined. This is making your associations load eagerly rather than lazily.

https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#fetching-fetchmode-join

Therefore, FetchMode.JOIN is useful for when entities are fetched directly, via their identifier or natural-id.

Also, the FetchMode.JOIN acts as a FetchType.EAGER strategy. Even if we mark the association as FetchType.LAZY, the FetchMode.JOIN will load the association eagerly.

Andronicus
  • 25,419
  • 17
  • 47
  • 88
Priyak Dey
  • 1,227
  • 8
  • 20
  • thank you! This is really not intuitive behavoir, but thank you once again for letting me know! – Alex Mi Mar 22 '20 at 05:46
  • Nice catch. Does that apply to `FetchMode.JOIN` only? – Andronicus Mar 22 '20 at 12:04
  • 1
    There are three fetch modes, Join, subselect and select. By default, it is select where it fires N+1 queries to fetch your associations. Subselect is used with collections types where a sub query is generated to select the associations. And join kind of overrides the LAZY cause , it fetches eagerly using a join (I think it is a left outer join it uses, but have to read the doc and do some example before I can surely say). – Priyak Dey Mar 23 '20 at 11:33
  • 1
    You can read in the documentation I mentioned, and I have to done some examples to check exactly how things work since I never used @Fetch. This is a hibernate specific annotation, and I always stick to JPA annotations unless there is no other way out. – Priyak Dey Mar 23 '20 at 11:33
  • @PriyakDey thank you a lot for your contributions! Strange to me, why other posts seem not to mention this fact, could you please check? For example: https://stackoverflow.com/questions/32984799/fetchmode-join-vs-subselect – Alex Mi Jun 14 '20 at 06:41