spring - How to design JPA polymorphic relationships in java? -
i designing product catalogue. have category tree, products can connected leafcategories, can have 1 parent category. using spring boot, spring data , hibernate 4 , h2 database(for now).
base entity task abstractcategory (is there better way inherit relationships ?) (getters , setters omitted, namedentity @mappedsuperclass string name , long id)
public abstract class abstractcategory extends namedentity{ @manytoone(cascade = cascadetype.persist) @joincolumn(name = "parentid") category parent; }
category entities - not leafs , cannot have products connected them:
@entity public class category extends abstractcategory { @onetomany(cascade = cascadetype.all, mappedby = "parent") collection<abstractcategory> subcategories; }
leafcategory can used property product entity.
@entity public class leafcategory extends abstractcategory { @onetomany(cascade = cascadetype.persist, mappedby = "category") collection<product> products; }
i have simple crudrepository category , identical leafcategory
@repository @transactional public interface categoryrepository extends crudrepository<category, long> {}
when load category categoryrepository , access getsubcategories() following exception:
caused by: org.hibernate.lazyinitializationexception: failed lazily initialize collection of role: uj.jg.domain.products.category.subcategories, not initialize proxy - no session
first of - how can improve design? second , more concrete question why @transactional
not keeping session open? know use fetchtype.eager
, it's recursive structure - if understanding of hibernate correct mean loading whole subtree, , don't want that. don't want use hibernate.initialize
either.
i not have config database or hibernate. using devtools spring.boot:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-devtools</artifactid> </dependency>
how can improve design?
it looks reasonable me.
why
@transactional
not keeping session open?
you have placed @transactional
on repository. db session open time of running query, returns categories subcategories marked lazy-loaded. then, session closed (once repository method returns) , trying access subcategories after that, when there's no session more. move @transactional
annotation higher call stack - service layer if using 3-layer architecture (cf. this post).
since repository methods run single query, there's no need mark them @transactional
- run within transaction anyway. makes sense have @transactional
when run several queries or run query , other processing (which throw exception , you'd want query rolled because of it). that's why, again, if want explicitly mark @transactional
rather in service layer.
Comments
Post a Comment