Hi,
I have been playing with collections for quite a while now and found 1 issue that I think would be a nice improvement (mind you I might just not be able to figure out how to use it correctly).
Problem description: Say you have a class Holder that colds a Collections of objects that are modelled with inheritance, it would be nice if you could limit the objects you want to have returned and hibernate realising that it is not necessary to join against that table.
In code:
{code:java} @Entity public static class Holder { @Id String holderId = UUID.randomUUID().toString(); @OneToMany(cascade=CascadeType.ALL) @JoinColumn(name="subclassID") List<A> elements; }
@Entity @Inheritance(strategy=InheritanceType.JOINED) public static class A { @Id String pkey = UUID.randomUUID().toString(); String type = "a"; String subclassID; @Override public String toString() { return "Class A, pkey: " + pkey + " Subclass " + subclassID; } }
@Entity public static class B extends A { String test; String type = "b"; @Override public String toString() { return "Class B, pkey: " + pkey + " Subclass " + subclassID + " Test: " + test; } }
@Entity public static class C extends A { String ello; String type = "c"; @Override public String toString() { return "Class C, pkey: " + pkey + " Subclass " + subclassID + " ello: " + ello; } } {code}
So in this example, Holder holds objects of A, B and C. This works perfectly fine when reqesting via Entitymanager:
{code:java} Holder find = em.find(Holder.class, "hid"); {code}
Hibernate requests Holder and then resolves all the entities correctly. It joins all tables.
However, when executing:
{code:java} em.createQuery("SELECT h FROM Holder h LEFT JOIN fetch h.elements e where TYPE(e) IN (B)", Holder.class); {code}
EDIT: If i do not use the "fetch" keyword, regardless of whether or not i use eager fetching, it always fetches any type.. I have not figured out why
The query executes fine, it resolves all types that are in B, however it unnecessarily joins C as well. From the query it is clear, that no element that is in table C can ever be represented in the elements collection since the type has to be of type B. So for that, hibernate could recognise it. Considering that there can be X different classes, this could be a significant performance improvement.
I hope that all makes sense - I "discovered" this trying to make it work without joining all tables. I guess I could generate my own native query and only join what I need.
I also documented my attempts and observations on this stackoverflow:
http://stackoverflow.com/questions/37973603/jpa-onetomany-collection-with-inheritance-limit-to-specific-subclass/
I hope that all makes sense - please let me know if something is unclear (or if I am just missing the right info and this actually already works).
My current workaround is to use EMF and simply filter in code since it joins every table anyway and I don't want to write custom queries, but rather use the EM directly. |
|