gpt4 book ai didi

java - Hibernate 4 延迟加载不起作用

转载 作者:行者123 更新时间:2023-11-30 08:27:24 25 4
gpt4 key购买 nike

我正在使用 spring 3 和 hibernate 4 开发一个网络应用程序。我在延迟加载用户所属组的一组授予权限时遇到问题。从数据库中检索用户对象时,即使显式调用了 user.getGroup().getPermissions(),其组对象也没有任何权限。

我注意到在 Debug模式下,如果我将鼠标悬停在 User 对象上,然后导航到 User 对象内的 Group 对象,然后导航到它的权限,我可以看到它的类型显示为 PersistentSet,并展开它将正确加载权限。但在非 Debug模式下,权限永远不会延迟加载。我在这里错过了什么?提前致谢。

以下是实体之间的关系:用户与组是一对多关系,组与权限是多对多关系。

这是UserDaoImpl类的定义

@Repository
@Transactional
public class UserDaoImpl implements UserDao {

@Autowired
private SessionFactory sessionFactory;

private Session getSession() {
return sessionFactory.getCurrentSession();
}

@Override
public User get(String username) {
Session session = getSession();
User user = (User) session.createCriteria(User.class).add(Restrictions.eq("username", username)).uniqueResult();

Group g = user.getGroup();

// calling g.getGrantedPermissions() doesn't load any permission
Set<Permission> permissions = g.getGrantedPermissions();
return user;
}
}

这是权限类的定义

@Entity
public class Permission {
@Id
@GeneratedValue
private Long id;

@Column
private String name;

@Column
private String description;

public Permission()
{

}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

这是Group类的定义

@Entity
@Table(name="\"Group\"")
public class Group {
public static final String ROLE_VALID_USER = "ROLE_VALID_USER";

@Id
@GeneratedValue
private Long id;

@Column
private String description;

@Column
private String role;

@ManyToMany
@JoinTable(name = "granted_permission",
joinColumns = {@JoinColumn(name = "GROUP_ID", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name = "PERMISSION_ID", nullable = false, updatable = false) })
private Set<Permission> grantedPermissions;

public Group()
{

}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getRole() {
return role;
}

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

public Set<Permission> getGrantedPermissions() {
return grantedPermissions;
}

public void setGrantedPermissions(Set<Permission> grantedPermissions) {
this.grantedPermissions = grantedPermissions;
}
}

这是User类的定义

@Entity
public class User {
@Id
@Column(name="USERNAME")
private String username;

@Column(name="PASSWORD")
private String password;

@Transient
private final boolean enabled = true;

@Column
private String name;

@Column(name="EMAIL")
private String email;

@Column(name="PHONE")
private String phone;

@ManyToOne
private Group group;

@ManyToOne
@JoinColumn(name="ORIGINAL_BRANCH_ID")
private Branch originalBranch;

@ManyToOne
@JoinColumn(name="ID_OF_RESPONSIBLE_BRANCH")
private Branch responsibleBranch;

public User()
{

}

public String getUsername() {
return username;
}

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

public String getPassword() {
return password;
}

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

public String getRole() {
return group.getRole();
}

public boolean isEnabled() {
return enabled;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}

public Group getGroup() {
return group;
}

public void setGroup(Group group) {
this.group = group;
}

public Branch getOriginalBranch() {
return originalBranch;
}

public void setOriginalBranch(Branch originalBranch) {
this.originalBranch = originalBranch;
}

public Branch getResponsibleBranch() {
return responsibleBranch;
}

public void setResponsibleBranch(Branch responsibleBranch) {
this.responsibleBranch = responsibleBranch;
}
}

这是持久性配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<tx:annotation-driven />

<context:annotation-config />

<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<context:component-scan base-package="net.acme.prs" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="packagesToScan" value="net.acme.prs" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5InnoDBDialect
</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>

<bean id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/prs" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
</beans>

最佳答案

我不明白你的问题是什么,因为你没有提到你遇到的任何错误。如果你只是单纯的发现没有SQL去获取grantedPermissions,这就是lazy-fetching的意思:只有被访问的时候才去获取,没有被访问的时候就不会去获取获取。

你看到它在调试期间被提取的原因是因为当你在调试器中检查 grantedPermissions 时,它正在访问那个属性,这将触发延迟提取.但是,对于非 Debug模式,如果您没有访问该属性的代码,则不进行提取正是它应该做的。


如果您要问的是,您有非 Debug模式的代码将访问 grantedPermissions 但在访问时延迟获取失败,那么这是由于访问超出事务: Hibernate 需要有一个 Activity 的 Session 才能进行延迟获取。如果延迟获取发生在事务之外,它将失败,因为没有打开的 Session。您应该通过考虑重新审视您的设计

  1. 交易范围:您应该将交易边界置于适当的工作单元级别,而不是围绕 DAO 进行交易:可能是您的应用服务或 Controller
  2. 进行适当的联合获取/预先获取,以便在事务之外不会发生延迟获取
  3. EclipseLink 是另一个 JPA 实现,它允许在 session 结束后延迟获取。

关于java - Hibernate 4 延迟加载不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20875656/

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