gpt4 book ai didi

java - 尝试访问已加载实体的集合时发生 LazyInitializationException

转载 作者:行者123 更新时间:2023-12-04 10:03:08 25 4
gpt4 key购买 nike

我在尝试访问 permissions 时遇到 LazyInitializationException我的 Collection User目的。异常信息:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: dev.teamnight.nightweb.core.entities.User.permissions, could not initialize proxy - no Session

这是 User 类的重要部分:
@Entity
@Table(name = "users")
@Inheritance(strategy = InheritanceType.JOINED)
public class User {

// [...] Other variables
@OneToMany
@JoinTable(
name = "user_groups",
joinColumns = @JoinColumn(name = "groupId"),
inverseJoinColumns = @JoinColumn(name = "userId")
)
private List<Group> groups = new ArrayList<Group>();

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
@OrderBy("name ASC")
private List<UserPermission> permissions;

// [...] Getter Setter

@Override
public boolean hasPermission(String permission) {
/**
* Check for User
* UserPermission has yes or no/neutral, no resolves to true, no/neutral to no, UserPermissions override all GroupPermissions, if no go to GroupPerms
* (Groups are sorted by priority, highest priority first, all permissions to one ArrayList)
* GroupPermission true allows, neutral ignores, false denies
*/
UserPermission userPerm = this.permissions.stream()
.filter(perm -> perm.getName().equals(permission))
.filter(perm -> perm.getType() == Permission.Type.FLAG)
.filter(perm -> perm.getAsBoolean())
.findFirst()
.orElse(null);

if(userPerm != null) {
return true;
}

boolean allow = false;

List<GroupPermission> groupPermissions = new ArrayList<GroupPermission>();

this.groups.forEach(group -> {
groupPermissions.addAll(group.getPermissions().stream().filter(perm -> perm.getType() == Permission.Type.FLAG).collect(Collectors.toList()));
});

for(GroupPermission perm : groupPermissions) {
Tribool bool = perm.getAsTribool();

if(bool == Tribool.TRUE) {
allow = true;
} else if(bool == Tribool.FALSE) {
return false;
}
}
return allow;
}

用户权限.java:
@Entity
@Table(name = "user_permissions", uniqueConstraints = @UniqueConstraint(columnNames = {"userId", "name"}))
public class UserPermission extends Permission {

@ManyToOne
@JoinColumn(name = "userId", nullable = false)
private User user;

}

UserHelper.java:
    public <T extends User> T getByUsername(String username, Class<T> type) {
Session session = this.factory().getCurrentSession();
session.beginTransaction();

Query<T> query = session.createQuery("FROM " + type.getCanonicalName() + " U WHERE U.username = :username", type);
query.setParameter("username", username);

T user = query.uniqueResult();
session.getTransaction().commit();

return user;
}

我正在调用 getByUsername() 从数据库接收用户,然后我尝试使用 User.hasPermission("testperm") 访问权限,然后发生上述异常。

编辑 : 提到还有另一个关联,所以 FetchType.EAGER 或 @Fetch(FetchMode.join) 导致另一个异常。

最佳答案

您有 2 个选项可以修复 LazyInitializationException .您可以使用多个 JOIN FETCH 子句来初始化所有必需的关联,或者您可以对每个必需的关联执行查询。我在最近关于 2 best options to fix Hibernate's MultipleBagFetchException 的文章中详细解释了这两者。 .

选项 1 - 多个 JOIN FETCH 子句

对于此选项,您需要将多对多关联的类型更改为 Set而不是 List .这可以防止 MulitpleBagFetchException获取多对多关联时。
在下一步中,您可以使用 JOIN FETCHes 所有必需关联的查询,例如:

SELECT u FROM User u LEFT JOIN FETCH u.permissions LEFT JOIN FETCH u.groups

如果您的查询创建的产品很小,这是一个很好的方法。在这种情况下,这意味着您只需选择几个 User实体,以及您的 permissionsgroups关联只包含几个实体。

选项 2 - 多个查询

Hibernate 确保在 Session 内,每个数据库记录仅映射到 1 个实体对象。因此,无论您选择 User 的频率如何id 为 1 的实体,Hibernate 将始终将其映射到相同的 User实体对象。您可以使用它来初始化多个关联,而不必担心 MultipleBagFetchException .
在本例中,您可以执行 2 个查询。第一个得到 User实体并初始化 permissions协会。第二个得到 User实体并初始化 groups协会。
SELECT u FROM User u LEFT JOIN FETCH u.permissions
SELECT u FROM User u LEFT JOIN FETCH u.groups

关于java - 尝试访问已加载实体的集合时发生 LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61734389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com