java - JPA/Hibernate load recursive object graph without N+1/cartesian products -
when converting project ibatis jpa 2.1, i'm faced problem have load finish object graph set of objects, without hitting n+1 selects or using cartesian products performance reasons.
a users query yield list<task>, , need create sure when homecoming tasks, have properties populated, including parent, children, dependencies , properties. first allow me explain 2 entity objects involved.
a task part of hierarchy. can have parent task , can have children. task can dependent on other tasks, expressed 'dependencies' property. task can have many properties, expressed properties property.
the illustration objects have been simplified much possible , boilerplate code removed.
@entity public class task { @id private long id; @manytoone(fetch = lazy) private task parent; @manytoone(fetch = lazy) private task root; @onetomany(mappedby = "task") private list<taskproperty> properties; @manytomany @jointable(name = "task_dependency", inversejoincolumns = { @joincolumn(name = "depends_on")}) private list<task> dependencies; @onetomany(mappedby = "parent") private list<task> children; } @entity public class taskpropertyvalue { @id private long id; @manytoone(fetch = lazy) private task task; private string name; private string value; } the task hierarchy given task can infinitely deep, create easier whole graph, task have pointer it's root task via 'root' property.
in ibatis, fetched tasks distinct list of root id's, , did ad-hoc queries properties , dependencies "task_id in ()" query. when had those, used java code add together properties, children , dependencies model objects graph complete. size list of tasks, 3 sql queries, , i'm trying same jpa. since 'parent' property indicates add together children, didn't have query those.
i've tried different approaches, including:
let lazy loading it's job performance suicide, no need elaborate :) join fetch children, bring together fetch dependences, bring together fetch properties this problematic because resulting cartesian products huge, , jpa implementation (hibernate) doesn't back upwards list, set when fetching multiple bags. task can have huge number of properties, making cartesian products ineffective. ad-hoc queries same way did in ibatis i cannot add together children, dependencies , properties lazy initialized collections on task objects, because hibernate seek add together them new objects.one possible solution create new task objects not managed jpa , sew hierarchy using those, , guess can live that, doesn't sense "jpa", , couldn't utilize jpa it's @ - tracking , persisting changes objects automatically.
any hints appreciated. i'm open using vendor spesific extensions if necessary. i'm running in wildfly 8.1.0.final (java ee7 total profile) hibernate 4.3.5.final.
available options
there strategies accomplish goals:
sub-select fetching load lazy entities additional sub-select, first time need lazy association of given type. sound appealing @ first, makes app fragile number of additional sub-select entities fetch , may propagate other service methods.
batch fetching easier control, since can enforce number of entities loaded in 1 batch , might not impact much other utilize cases.
using recursive mutual table expression if db supports it.
plan aheadin end it's plan on doing selected rows. if it's displaying them view, native query more enough. if need retain entities across multiple requests (first view part, sec update part) entities improve approach.
from response see need issue entitymanager.merge() , rely on cascading propagate children state transitions (add/remove). since talking 3 jpa queries , long don't cartesian product should fine jpa.
conclusionyou should strive minimum amount of queries doesn't mean have have 1 , 1 query. 2 or 3 queries not issue @ all. long command queries number , don't n+1 issue fine more 1 query too. trading cartesian product (2 one-to-many fetches) 1 bring together , 1 additional select deal anyway.
in end should check explain analyze query plan , reinforce/rethink strategy.
java hibernate jpa lazy-loading java-ee-7
No comments:
Post a Comment