JPA合并操作未按预期工作

时间:2014-01-13 20:22:38

标签: java hibernate jpa

我的控制器中有一个方法,它接受一个Employee列表作为参数。它们是我想要更新到DB的更新对象。

public static void save(Project project, List<ClientEmployee> clientEmployees){
   ...
   //project is currently associated with current hibernate session.
   //no clientEmployees are associated with current session, however all have id's.

   for(ClientEmployee newClientEmployee : clientEmployees){
      if(newClientEmployee != null){
          ClientEmployee clientEmployee = JPA.em().merge(newClientEmployee);
          //clientEmployee.role = newClientEmployee.role;
          project.addClientEmployee(clientEmployee);
      }
   }

}

当我调用merge时,返回的对象clientEmployee没有来自newClientEmployee的更新信息。这是为什么?据我所知,hibernate将尝试查找具有相同标识符的对象,并在复制字段后加载它?

所以我认为可能是我保存后才更新信息。但即使在project.save();之后它也不会更新对象,也不会更新数据库中的行。

实施例..

clientEmployee.name = "John Snow"; //Current id = 1, not attached to session.
ClientEmployee persitedEmployee = JPA.em().merge(clientEmployee) //DB row has id 1, but name is null

此时persitedEmployee.name仍然为空。

2 个答案:

答案 0 :(得分:0)

不要对clientEmployee.name = "John Snow";等属性使用公共访问权限,但这不起作用。将属性设为私有或受保护并创建getter / setter,通过setter设置属性,如下所示:clientEmployee.setName("John Snow");

请参阅Hibernate proxy pitfalls post

代理陷阱1:字段访问

  

使用代理进入第一个陷阱:加载代理时,   数据不存储在thr代理对象中,而是存储在“目标”对象中。   代理对象中的字段将永远保持为null(或任何值   他们已经初始化了),因为调用了所有方法   代理将被委托给目标对象。

     

...

     

为了防止这种情况,请在这些场合使用getter和setter。代理人   将在调用getter并且数据将被加载时加载   访问。

答案 1 :(得分:0)

独立实体

您正在使用的是分离的实体。

对于新的Entities,您必须使用.persist()

对于现有的Entities,您需要.merge()您的实体进入EntityManager上下文,它会自动保留更新的数据。

注意: 您传入的引用将进行管理,.merge()会创建副本并将副本添加到上下文中。

交易

您必须在交易中执行.merge()才能使其发挥作用。

JPA.em().startTransaction();
ClientEmployee clientEmployee = JPA.em().merge(newClientEmployee);
JPA.em().commitTransaction();

当然,您需要在try/catch/finally块内执行此操作,并在失败时调用JPA.em().rollbackTransaction()并在finally块中调用JPA.em().close()

刷新

您还可以执行JPA.em().refresh(newClientEmployee);以确保从数据存储中提取任何动态创建的字段。这不必在交易中完成。