5

Hibernate 5.0.10 I have a subgraph defined that looks like this:

@NamedSubgraph(name = "proc", attributeNodes = { @NamedAttributeNode("name"), @NamedAttributeNode("childTable1"), @NamedAttributeNode("childTable2"), @NamedAttributeNode("childTable3"), @NamedAttributeNode("childTable4") }),

The problem is that when using this subgraph, I'm getting back all attributes defined in the root table (where name exists), not just the subgraph attributes I've specified. Is there a way to tell hibernate to not fetch those children? My query looks just like select rec from records rec join rec.proc

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
John Ament
  • 11,595
  • 1
  • 36
  • 45

2 Answers2

4
  1. If you're talking about basic types, then, by default, Hibernate will always fetch them. The only way to enable it is to set @Basic(fetch=LAZY) on the entity attribute and enable bytecode enhancement.
  2. If you're talking about EAGER associations, then Hibernate cannot override them to LAZY, even if the JPA standard says it should.

These strategies are not mandatory requirements from a JPA perspective because LAZY is just a hint for the JPA provider.

All in all, JPA entity graphs are a suboptimal way of fetching data. Avoiding FetchType.EAGER associations, using subentities, and DTO projections are much better than entity graphs.

Most of the time, you don't even need to fetch entities because entities make sense only if you plan to modify them. Otherwise, a DTO projection will always be way more efficient.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • Well in this case, eager loading is only part of the issue. I'm curious about the DTO approach. Are you talking about mapping the result set into an entity? Rather than an `Object[]`? – John Ament Feb 13 '17 at 19:33
  • In addition, when looking at the bytecode enhancement, would I still need `@Basic(LAZY)` on the attributes? – John Ament Feb 13 '17 at 19:39
  • You can map the result directly into a DTO using the constructor clause or the Hibernate `ResultTransformer`. As for BE, I guess you need `@Basic(LAZY)` to enable lazy loading for attributes. Otherwise, the basic attributes are EAGER. – Vlad Mihalcea Feb 13 '17 at 19:41
  • Atleast in 5.0.10, you cannot do that with DTO as I'm explicitly loading child entities. It fails because the attribute isn't the root of the select. – John Ament Feb 13 '17 at 20:07
  • 1
    Whatever you want to do with subgraphs, you can also do we with JPQL queries as long as associations are LAZY and you JOIN FETCH explicitly the ones you want to load. – Vlad Mihalcea Feb 13 '17 at 20:19
  • I'm not seeing how that's relevant. I'm noting a potential issue with DTOs. Do you have a way around that problem? I agree, it fixes my problem a bit better than needing graphs. – John Ament Feb 13 '17 at 20:48
  • Can you elaborate why you cannot use DTO with Hibernate 5.0? I don't understand what's holding you back. – Vlad Mihalcea Feb 13 '17 at 20:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/135630/discussion-between-john-ament-and-vlad-mihalcea). – John Ament Feb 13 '17 at 21:12
1

I wrote an article about all the problems that you might run into when using the entity model here if you are interested. So in general you should avoid that if possible. You might want to give Blaze-Persistence Entity Views a try which is exactly it's use case. You can define the target structure i.e. the DTO as interface and map attributes to JPQL expressions. This also supports collections and so on but works on JPQL level instead of SQL level.

Christian Beikov
  • 15,141
  • 2
  • 32
  • 58