my2iu / Jinq

LINQ-style queries for Java 8
Other
659 stars 71 forks source link

Please add support for dynamic JPA 2.1 Entity Graph #73

Closed throwable closed 5 years ago

throwable commented 6 years ago

Something like this:

myEntityStream.fetch(me -> Arrays.asList(me.getProperty1(), me.getProperty2(), me.getEntity().getProperty()))

That will construct an Entity Graph and apply to the query:

EntityGraph<MyEntity> eg = em.createEntityGraph(MyEntity.class);
eg.addAttributeNodes("property1");
eg.addAttributeNodes("property2");
eg.addAttributeNodes("entity.property");
...
Properties props = new Properties();
props.put("javax.persistence.fetchgraph", eg);
...
my2iu commented 6 years ago

I'm no longer doing any active development on Jinq, so I don't have the cycles to look at this, but I'll keep the issue around in case the situation changes.

ronelm2000 commented 5 years ago

Another slightly less intrusive fix for this should be a way to propagate JINQ Hints to JPA.

...
EntityGraph<MyEntity> eg = em.createEntityGraph(MyEntity.class);
eg.addAttributeNodes("property1");
eg.addAttributeNodes("property2");
eg.addAttributeNodes("entity.property");

myEntityStream = myEntityStream.setHint("javax.persistence.fetchgraph", eg);
...

As far as I'm know FetchGraphs in JPA 2.1 onwards are just treated as hints and fetch has a clearly defined output (using fetch joins). At most this has to be a new API and not on existing .fetchJoin methods.

stream.fetchGraph(me -> {
me.getProperty1(); 
me.getProperty2();
me.getEntity().getProperty();
})
my2iu commented 5 years ago

Ok, implemented. I'm not entirely sure it's working as intended though. EclipseLink didn't seem to do anything with a small query that I tried to use it with, and Hibernate did do something, but the result seemed really sub-optimal.

my2iu commented 5 years ago

This is now in the 1.8.26 release of Jinq.

ronelm2000 commented 5 years ago

@my2iu found the problem:

      else if ("javax.persistence.fetchgraph".equals("name") && val instanceof EntityGraph)
         javaxPersistenceFetchgraph = (EntityGraph<?>)val;

I believe it should be "javax.persistence.fetchgraph".equals(name), correct?

The expected output iirc is dependent on the implementation sadly. Hibernate iirc will STILL load eager bindings, while EclipseLink will force all other eager attributes to become lazy.

my2iu commented 5 years ago

You're right. Sorry about that. I was rushing through things and never bothered tracking down why the test case wasn't causing EclipseLink to generate different SQL than before. That change, plus some strange incantations to get EclipseLink weaving working under Maven, seems to cause EclipseLink to generate different SQL.

The fix has now been released in 1.8.27.