0

I am getting the below error: when I am trying to save my data.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.model.User.userRole, could not initialize proxy - no Session

I have listed the classes that I have used.

A User.java:

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "users", catalog = "test")
public class User {

private String username;
private String password;
private boolean enabled;
private Set<UserRole> userRole = new HashSet<UserRole>(0);

public User() {
}

public User(String username, String password, boolean enabled) {
    this.username = username;
    this.password = password;
    this.enabled = enabled;
}

public User(String username, String password, 
    boolean enabled, Set<UserRole> userRole) {
    this.username = username;
    this.password = password;
    this.enabled = enabled;
    this.userRole = userRole;
}

@Id
@Column(name = "username", unique = true, 
    nullable = false, length = 45)
public String getUsername() {
    return this.username;
}

public void setUsername(String username) {
    this.username = username;
}

@Column(name = "password", 
    nullable = false, length = 60)
public String getPassword() {
    return this.password;
}

public void setPassword(String password) {
    this.password = password;
}

@Column(name = "enabled", nullable = false)
public boolean isEnabled() {
    return this.enabled;
}

public void setEnabled(boolean enabled) {
    this.enabled = enabled;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
public Set<UserRole> getUserRole() {
    return this.userRole;
}

public void setUserRole(Set<UserRole> userRole) {
    this.userRole = userRole;
}

}

And a UserRole.java:

import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "user_roles", catalog = "test", uniqueConstraints =  UniqueConstraint(columnNames = { "role", "username" }))
public class UserRole{

private Integer userRoleId;
private User user;
private String role;

public UserRole() {
}

public UserRole(User user, String role) {
    this.user = user;
    this.role = role;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "user_role_id", 
    unique = true, nullable = false)
public Integer getUserRoleId() {
    return this.userRoleId;
}

public void setUserRoleId(Integer userRoleId) {
    this.userRoleId = userRoleId;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "username", nullable = false)
public User getUser() {
    return this.user;
}

public void setUser(User user) {
    this.user = user;
}

@Column(name = "role", nullable = false, length = 45)
public String getRole() {
    return this.role;
}

public void setRole(String role) {
    this.role = role;
}

}

And I have a Dao Implemented:

@Transactional
@Override
@SuppressWarnings("unchecked")
public List<User> listUsers() {
    return this.sessionFactory.getCurrentSession()
            .createCriteria(User.class).list();
}

I am listing all users in my controller with the "listUsers" method. And add with model.addObject("users", listUsers);.

In the view, i use the following code:

<c:forEach items="${users}" var="user">
    Username: ${user.username}
    Pass:     ${user.password}
    Role:     ${user.userRole}
</c:foreEach>

But I got the above error (because of the ${user.userRole} variable):

So how can I print out the role of the users (like: normal user, admin)?

User27854
  • 747
  • 10
  • 32
Roberto
  • 170
  • 2
  • 15

2 Answers2

0

Your session is only available to execute your Criteria. After that, it's closed and it's not available. The proxied fields depend on the session to be recovered later, but since the session is already closed, then you get the exception message about LazyInitializationException.

To solve it, retrieve the data while the session is still open, or do not mark such fields as FetchType.LAZY.

Luiggi Mendoza
  • 81,685
  • 14
  • 140
  • 306
  • @Roberto *To solve it, retrieve the data while the session is still open, or do not mark such fields as `FetchType.LAZY`*. – Luiggi Mendoza Oct 23 '14 at 17:03
  • But if I change it to FetchType.EAGER, every user with admin role has two entry like: user1, admin1, admin1, user2, user3, admin2, admin2 – Roberto Oct 23 '14 at 17:06
  • @Roberto then find a way to make your session live more than just that method, then retrieve the necessary fields by calling the proper getter while the session is still open/alive. Otherwise, you will continue having this problem. – Luiggi Mendoza Oct 23 '14 at 17:07
0

From your comments on the answer from @Luiggi Mendoza, it seems like you just need to keep your sessions open longer. Take a look at this answer to a highly similar question. The solution there is to change your configuration to have your session last the lifetime of the thread with the following:

<property name="current_session_context_class">thread</property> 
Community
  • 1
  • 1
Justin Johnson
  • 29,495
  • 7
  • 60
  • 86