Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在Hibernate中实现延迟加载,其中模型是在使用属性的不同事务中创建的_Java_Spring_Hibernate_Transactions_Lazy Loading - Fatal编程技术网

Java 如何在Hibernate中实现延迟加载,其中模型是在使用属性的不同事务中创建的

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

我知道这已经被问过很多次了,但我看不到这个特殊情况的确切答案:

我有一个控制器类,它在两个不同的方法中处理onLoad(…)和onSubmit(…)上的
@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