persistence icon indicating copy to clipboard operation
persistence copied to clipboard

Hint to prevent provider loading state beyond what graph specifies

Open lukasj opened this issue 11 years ago • 7 comments

JPA 2.1 introduced the concept of fetch graphs and load graphs. In a fetch graph attributes that are specified are treated as EAGER.

Unfortunately, there is no strong facility to specify which data should definitely NOT be loaded. Often limiting what should be loaded is even more important than specifying what should be loaded.

The functioning of fetch graphs is specifically hampered by the very unfortunate appearance of section 3.7.4 in the JPA 2.1 spec:

The persistence provider is permitted to fetch additional entity state beyond that specified by a fetch graph or load graph. It is required, however, that the persistence provider fetch all state specified by the fetch or load graph.

I would like to propose adding either an additional hint, to be used together with the fetch and load graph hints, or two new hints in addition to the fetch and load graph hints, that forbid the provider to load any additional state beyond that what is specified.

The definition of these new hints could be something like:

The persistence provider is strongly forbidden to fetch any additional entity state beyond that specified by a fetch graph or load graph. It is required that the persistence provider fetch all state specified by the fetch or load graph.

lukasj avatar Nov 19 '14 20:11 lukasj

  • Issue Imported From: https://github.com/javaee/jpa-spec/issues/96
  • Original Issue Raised By:@glassfishrobot
  • Original Issue Assigned To: @ldemichiel

lukasj avatar Aug 31 '18 16:08 lukasj

@glassfishrobot Commented Reported by @arjantijms

lukasj avatar Nov 19 '14 20:11 lukasj

@glassfishrobot Commented This issue was imported from java.net JIRA JPA_SPEC-96

lukasj avatar May 05 '17 06:05 lukasj

The functioning of fetch graphs is specifically hampered by the very unfortunate appearance of section 3.7.4 in the JPA 2.1 spec:

The persistence provider is permitted to fetch additional entity state beyond that specified by a fetch graph or load graph. It is required, however, that the persistence provider fetch all state specified by the fetch or load graph.

I'm very much against removing this language. We should always let the implementation be less-than-optimally-efficient, for lots of reasons. I mean, implementing JPA is already very hard. The more unnecessary constraints we add, the fewer conforming implementations we will have.

This is a very old issue. Do we need to keep it around, or can I close it, @arjantijms?

gavinking avatar Aug 11 '23 17:08 gavinking

It's indeed a very old issue, but it has never been addressed and I feel that it's still valid. An Implementation should, obviously, be implementable and we should not make it unnecessary hard to implement.

On the other hand, we should also not make it unnecessary hard for users to implement certain things using framework either. Where do we put the responsibility and on who do we put this burden of essentially filtering out unwanted data?

Also, maybe some APIs by now have grown so much that a new implementation is hard / near impossible regardless. E.g. I wouldn't expect a new implementation of Faces to ever emerge, even if Faces was super popular again.

Unless you really think asking the persistence implementation to filter out unwanted data is unreasonable hard, I hope we can keep this open. Otherwise, close it, if this is really too hard.

arjantijms avatar Aug 12 '23 22:08 arjantijms

I mean, consider, for example:

  • The case where an associated object is already available in the PC. Are you really going to force me to return an uninitialized proxy in that case?
  • What about if it's only available in the second-level cache?
  • What am I allowed to do when executing in environments where bytecode processing tricks are disfavored? Remember that EntityGraph is not only about association fetching but also about field-level lazy fetching, which requires bytecode processing.

The spec defined fetch=LAZY as a hint for really good reasons, because implementations need quite a lot of flexibility here.

If EntityGraph were only about association fetching I might take a different view. But it's a thing that can only really be implemented using bytecode processing and dynamic generation of SQL at runtime. So a really perfect implementation of this API is, indeed, quite hard, compared to other features of JPA.

gavinking avatar Aug 12 '23 23:08 gavinking

I mean, if we restrict things the way you suggest, consider what would be implied by section 3.7.5.1.

It tells my that by default I'm supposed to fetch just the version property of every terminal entity of the graph. It's asking me to do a whole extra join just to fetch an almost-certainly-useless version of an entity I'm not even loading!

Fortunately, since laziness if always a hint in the JPA spec, this isn't a hard requirement for compliance with JPA.

So in Hibernate we just ignore this. If we're already going to the effort of joining a table, we go ahead and fetch more than just the version. And that's perfectly complaint behavior.

Now, sure, you could argue that our interpretation of the spec isn't very faithful to its original intent, and you might be right. But, y'know, we don't much like being faithful to requirements that seem crazy to us.

gavinking avatar Aug 12 '23 23:08 gavinking