【问题标题】:org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessionsorg.hibernate.HibernateException:非法尝试将代理与两个打开的会话相关联
【发布时间】:2015-12-29 06:13:06
【问题描述】:

我正在使用 spring 和 hibernate 进行休息服务,用于使用以下代码更新员工数据,但运行时出现以下错误

{
  "code": 0,
  "message": "org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions"
}

DataDaoImpl.java

 @Override  
   public Employee getEntityById(long id) throws  Exception {  
   session = sessionFactory.openSession();  
    Employee employee = (Employee) session.load(Employee.class,  
  new Long(id));  
  tx = session.getTransaction();  
 session.beginTransaction();  
  tx.commit();  
 return employee;  
 }   

RestController.jav

 @RequestMapping(value = "/save/{id}", method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
  public   @ResponseBody  
 Status  saveUser(@PathVariable("id") long id,@RequestBody Employee employee) {
 Employee employeeupdate = null;  

 try {  
     employeeupdate  =   dataServices.getEntityById(id); 
     employeeupdate.setFirstName(employee.getFirstName());
     employeeupdate.setLastName(employee.getLastName());
     employeeupdate.setEmail(employee.getEmail());
     employeeupdate.setPhone(employee.getPhone());
     dataServices.updateEntity(employeeupdate);

       return new Status(1, "Employee updated Successfully !");  
      } catch (Exception e) {  
       // e.printStackTrace();  
       return new Status(0, e.toString());  
      }  
  }  

 @Override  
 public boolean updateEntity(Employee    employeeupdate) throws Exception {  

 session = sessionFactory.openSession();  
  tx = session.beginTransaction();  
  session.update(employeeupdate);  
  tx.commit();  
  session.close();  

    return false;  
 }  

我在这里犯了什么错误?

【问题讨论】:

    标签: eclipse spring hibernate


    【解决方案1】:

    getEntityById(...) 方法中,会话没有关闭。在返回员工之前使用session.close(); 关闭会话并尝试。

    【讨论】:

    • 附带说明,您可以考虑使用getCurrentSession(),而不是使用openSession()。使用getCurrentSession() 会话绑定到上下文,应用程序不需要显式关闭。同样openSession()always 返回Session 的新实例,而getCurrentSession() 返回与该上下文关联的会话。
    【解决方案2】:

    不要打开 2 个会话。只需打开一个即可使用。

    放置

    session = sessionFactory.openSession();  
    tx = session.beginTransaction(); 
    

    在 saveUser() 的开头并将会话/事务传递给方法。实际上你不需要在 getEntityById() 中进行交易——你什么都没有改变。

    【讨论】:

    • 对不起,在一般情况下,他需要一个读取事务。可能在这种情况下它不是很有用,但不使用事务进行读取可能会导致list() 出现空结果问题。
    【解决方案3】:

    @StanislavL 的答案,您的代码 getEntityById() 应该有一些错误(您需要关闭会话并将事务放在 load() 上方)。

    @Override  
       public Employee getEntityById(long id) throws  Exception {  
        session = sessionFactory.openSession();  
        tx = session.getTransaction();  
        session.beginTransaction();  
        Employee employee = (Employee) session.load(Employee.class,  
             new Long(id));  
        tx.commit();  
        session.close();
        return employee;  
     }   
    

    但是这个变体也不是很正确,你应该使用 finally 块捕获异常并回滚事务。最好的方法是使用这种模式doInTransaction()

    更新

    最好以这种方式获取实体

    Employee employee = (Employee) session.get(Employee.class,  id);
    

    【讨论】:

    • 我不仅使用 getEntityById() 方法更新用户,我还使用它来单独检索用户详细信息。如果我加载它可以吗
    【解决方案4】:

    简而言之,您不应该在 DAO 中创建会话。

    鉴于您使用的是 Spring,您应该避免手动创建 Session/Transaction。请使用 Spring 管理事务和会话创建,依靠 Spring 的事务控制和 LocalEntityManagerFactoryBean 之类的东西

    【讨论】:

      猜你喜欢
      • 2011-03-06
      • 1970-01-01
      • 2015-10-11
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多