我的控制器中有一个方法,它接受一个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
仍然为空。
答案 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);
以确保从数据存储中提取任何动态创建的字段。这不必在交易中完成。