Java 如何在Hibernate中实现延迟加载,其中模型是在使用属性的不同事务中创建的
我知道这已经被问过很多次了,但我看不到这个特殊情况的确切答案: 我有一个控制器类,它在两个不同的方法中处理onLoad(…)和onSubmit(…)上的Java 如何在Hibernate中实现延迟加载,其中模型是在使用属性的不同事务中创建的,java,spring,hibernate,transactions,lazy-loading,Java,Spring,Hibernate,Transactions,Lazy Loading,我知道这已经被问过很多次了,但我看不到这个特殊情况的确切答案: 我有一个控制器类,它在两个不同的方法中处理onLoad(…)和onSubmit(…)上的@RequestMapping(params=“type”,method=RequestMethod.GET)和@RequestMapping(method=RequestMethod.POST) 然后,这些方法调用 @Transactional() 无效负载(TypeOfForm表单、Long id、TypeOfSessionParams se
@RequestMapping(params=“type”,method=RequestMethod.GET)和@RequestMapping(method=RequestMethod.POST)
然后,这些方法调用
@Transactional()
无效负载(TypeOfForm表单、Long id、TypeOfSessionParams sessionParams);
及
@Transactional()
作废存储(表格类型);
分别在逻辑类上
load方法转到dao并从数据库中获取模型的实例;但该模型包含以下内容:
@OneToMany(mappedBy=“company”,cascade=CascadeType.PERSIST)
公共集getCompanyLocations(){
返回companyLocations;}
只有使用store()
方法才能调用此函数。因为它是惰性加载,我得到:
org.hibernate.LazyInitializationException:未能延迟初始化角色集合:org.orgName.modelName.companyLocations,无法初始化代理-无会话
我看到的典型答案是:
添加@Transactional()
注释
我已经在load()和store()方法中找到了这个。我做错了吗?因为它似乎没有帮助(我认为是因为getCompanyLocations方法在store()中调用,这与最初创建模型对象时的事务不同)
向模型属性的get方法添加,fetch=FetchType.EAGER
这可能有效,我不知道-它使页面加载时间太长,我放弃了它-所以它不是一个有效的解决方案无论如何
使用OpenSessionInviewWinterCeptor/过滤器
实际上,据我所知,应用程序目前使用这两种方法:
在applicationContext-hibernate.xml文件中:
在web.xml中:
在视图中打开会话
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
sessionFactoryBeanName
会话工厂
在视图中打开会话
*.jsp
将true
添加到我的sessionFactory属性
这是唯一有效的解决方案,但我看过的所有地方都说这是一个非常糟糕的主意
那么,正确的方法是什么呢
如果有帮助,下面是TransactionalWebRequestInterceptor
类:
公共类TransactionalWebRequestInterceptor实现WebRequestInterceptor,TransactionDao{
私有静态最终日志日志=LogFactory.getLog(TransactionalWebRequestInterceptor.class);
私有平台transactionManager transactionManager;
私人交易属性交易属性;
private ThreadLocal threadTransactionStatus=new ThreadLocal();
public void setTransactionManager(PlatformTransactionManager transactionManager){
this.transactionManager=transactionManager;
}
公共无效设置TransactionaAttribute(TransactionaAttribute TransactionaAttribute){
this.transactionAttribute=transactionAttribute;
}
public void预处理(WebRequest)引发异常{
log.debug(“预处理”);
beginTransaction();
}
public void postHandle(WebRequest请求,ModelMap模型)引发异常{
log.debug(“postHandle”);
commitTransactionIfNoErrors();
}
public void afterCompletion(WebRequest请求,异常e)引发异常{
日志调试(“完成后”);
回滚TransactionIFinProgress();
}
public void setRollbackOnly(){
log.debug(“setRollbackOnly”);
TransactionStatus状态=threadTransactionStatus.get();
如果(状态==null){
调试(“已请求回滚,但没有正在进行的事务”);
返回;
}
status.setRollbackOnly();
}
私有无效开始交易(){
if(threadTransactionStatus.get()!=null)
抛出新的IllegalStateException(“事务已在进行”);
TransactionStatus状态=transactionManager.getTransaction(transactionAttribute);
threadTransactionStatus.set(状态);
log.debug(“事务开始”);
}
私有无效委托交易无错误(){
TransactionStatus状态=threadTransactionStatus.get();
如果(状态==null)
抛出新的非法状态异常(“无正在进行的事务”);
if(status.isRollbackOnly()){
调试(“commitTransactionIfNoErrors:事务仅为回滚;未提交”);
返回;
}
UserAttributes.getCurrent().getUser().setIsTransactionCompleted(true);
threadTransactionStatus.set(null);
transactionManager.commit(状态);
log.debug(“事务已提交”);
}
私有无效回滚事务处理IFinProgress(){
TransactionStatus状态=threadTransactionStatus.get();
如果(状态==null){
调试(“rollBackTransactionIfInProgress:没有正在进行的事务”);
返回;
}
threadTransactionStatus.set(null);
transactionManager.rollback(状态);
调试(“事务回滚”);
}
}
您应该在同一个事务中进行加载和存储,因此调用load和store的任何方法都应该是@Transactional
延迟加载问题通常通过使用一个专门的DTO模型来解决,该模型能够准确地获取所需的内容。我在这里写了一些解决方案及其优缺点:
如果您有两个请求,那么您有两个选择。使用存储区中的EntityManager.merge将状态按原样应用于数据库,或使用EntityManager.find加载现有数据并应用c