【问题标题】:Hibernate: failed to lazily initialize a collectionHibernate:无法延迟初始化集合
【发布时间】:2014-12-19 10:17:54
【问题描述】:

我收到以下错误:当我尝试保存数据时。

org.hibernate.LazyInitializationException: 延迟初始化失败 角色集合:com.test.model.User.userRole,不能 初始化代理 - 没有会话

我已经列出了我使用过的类。

一个用户.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;
}

}

还有一个 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;
}

}

我已经实现了一个道:

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

我正在使用“listUsers”方法列出我的控制器中的所有用户。并用 model.addObject("users", listUsers); 添加。

在视图中,我使用以下代码:

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

但我得到了上述错误(因为 ${user.userRole} 变量):

那么如何打印出用户的角色(例如:普通用户、管理员)?

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    您的会话仅可用于执行您的Criteria。之后,它被关闭并且不可用。代理字段取决于稍后要恢复的会话,但由于会话已经关闭,因此您会收到有关 LazyInitializationException 的异常消息。

    要解决这个问题,请在会话仍然打开时检索数据,或者不要将这些字段标记为FetchType.LAZY

    【讨论】:

    • @Roberto 要解决它,请在会话仍处于打开状态时检索数据,或者不要将此类字段标记为FetchType.LAZY
    • 但是如果我将其更改为 FetchType.EAGER,每个具有管理员角色的用户都有两个条目,例如:user1、admin1、admin1、user2、user3、admin2、admin2
    • @Roberto 然后找到一种方法让您的会话不仅仅是该方法,然后在会话仍处于打开/活动状态时通过调用适当的 getter 来检索必要的字段。否则,您将继续遇到此问题。
    【解决方案2】:

    根据@Luiggi Mendoza 的回答,您的 cmets 似乎只需要让您的会话保持更长时间。看看this answer 一个高度相似的问题。解决方案是更改您的配置以使您的会话在线程的生命周期中持续使用以下内容:

    <property name="current_session_context_class">thread</property> 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      • 2020-05-10
      • 2021-03-13
      • 1970-01-01
      相关资源
      最近更新 更多