Teaching myself Hibernate, I have the following table structure/relationship
Which is represented by the following classes...
@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
}
@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.
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())
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With