Overcoming lazy loading problems in Hibernate, many-to-many relationships

Teaching myself Hibernate, I have the following table structure / relation

Relationship

which is represented by the following classes ...

Users

@Entity @Table(name = "users") public class User implements IUser<Role>, Serializable { @Id @GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY) @SequenceGenerator(name = "user_key_seq") @Column(name = "key", insertable = false, updatable = false) private Long key; @Column(name = "name") private String name; @ManyToMany(cascade = {CascadeType.ALL}) @JoinTable(name = "userroles", joinColumns = { @JoinColumn(name = "userkey")}, inverseJoinColumns = { @JoinColumn(name = "rolekey")}) private Set<Role> roles = new HashSet<>(5); @Override public Set<Role> getRoles() { return roles; } // Other setters and getters } 

Roles

 @Entity @Table(name = "roles") public class Role implements IRole, Serializable { @Id @GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY) @SequenceGenerator(name = "roles_key_seq") @Column(name = "key", insertable = false, updatable = false) private Long key; @Column(name="name") private String name; @ManyToMany(cascade = {CascadeType.ALL}) @JoinTable(name="parentroles", joinColumns = {@JoinColumn(name="childkey")}, inverseJoinColumns = {@JoinColumn(name="parentkey")}) private Set<Role> roles = new HashSet<>(5); // Other setters and getters } 

The problem I get is ...

 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.kaizen.chishiki.core.data.User.roles, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575) at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214) at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554) at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142) at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180) at og.kaizen.chishiki.core.testdatacore.Main.<init>(Main.java:37) at og.kaizen.chishiki.core.testdatacore.Main.main(Main.java:25) 

Now I know that I can set the fetch type to FetchType.EAGER , but I would prefer not to do this, besides performance issues, I'm trying to study my problems around these problems;)

I was wondering if there is a way to write a Hibernate request to satisfy this relationship and manually load the lines (this would also allow me to return the Role interface instead of the implementation, as I need to do now (will allow me to support this contract)).

From what I read, it would seem that I need to build an Entity for UserRoles . Not that I'm against this decision, but I was curious if there was a way around it.

roles appears in many other respects, so it cannot create a direct link to the parent table (that is, I cannot put the key parent table in the Role table, in addition, users can have multiple roles )

Another solution I had in mind was to write a stored procedure to do this for me. Although this is a viable solution that I donโ€™t make, it makes the migration of the application to another database more difficult and not a trial traffic jam, but I try to remember these ideas.

+6
source share
3 answers

If you want to load users with your roles, but still keep the association lazy, use the HQL query containing left join fetch :

 select u from User u left join fetch u.roles where ... 

If you have a User and want to make sure that his role collection is initialized before the session is closed, call Hibernate.initialize(user.getRoles()) .

+4
source

If you are using Hibernate 4.1.6+, then you can deal with these lazy association problems by using the hibernate.enable_lazy_load_no_trans property in hibernate.properties.

See fooobar.com/questions/97734 / for more details.

+1
source

I solved this problem by annotating the method in the controller as transactional. Since lazy loading basically returns a list of future objects, the method should be transactional.

0
source

Source: https://habr.com/ru/post/971996/


All Articles