Overcoming lazy loading issues in Hibernate, many-to-many, relationship
hibernate, java
Solution
If you want to load users with their roles, but still keep the association lazy, use a HQL query containing a `left join fetch`:
select u from User u left join fetch u.roles where ...
If you have a User and want to make sure its roles collection is initialized before closing the session, call `Hibernate.initialize(user.getRoles())`.
Problem
Teaching myself Hibernate, I have the following table structure/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'm getting is this... ``` 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 I could set the `fetch` type to `FetchType.EAGER`, but I'd prefer not to do that, apart from performance concerns, I'm trying to learn my way around these problems ;) I was wondering if there was a way to write a Hibernate query to satisfy this relationship and load the rows manually (it would also allow me to return the interface of `Role` instead of the implementation as I'm having to do now (would allow me to maintain that contract)). From what I've read, it would seem that I would need to construct an `Entity` for `UserRoles`. Not that I'm against this solution, but I was curious if there was a way to get around it. `roles` appears in a number of other relationships, so there is no way it can form a direct relationship with the parent table (that is, I can't put the `key` of the parent table in the `role` table directly, besides, `users` can have multiple `roles`) The other solution I had in mind was to write a stored procedure to do it for me. While this is viable solution that I'm not above doing, it does make migrating the application to another database more difficult, not a show stopper, but I'm trying to keep these ideas in mind.