我对更改实体并想以其他方式更新它的事务处理方法有疑问。
首先,我使用entitymanager方法“ get”从数据库中获得实体 A 。 然后我得到一个相关的实体 B ,其中 A到B 是一对一的类型(可选)。 (因此B的id字段在A的表内)。现在,我想通过服务方法删除实体 B 。因此,我必须使用 B 的 ID 。
在实体管理器的服务方法i get B中(现在为B')。然后我从获得的 B'中得到 A'。然后,当通过 A'.setB(null)后跟 serviceOfA的链接出现时,我删除到 B'的链接 A' .save(A')。
然后我通过 serviceOfB.delete(B')删除 B'。
通过id删除B的方法完成后,我想更改实例A的属性。 例如,创建另一个 B 实例。现在当我再次通过entitymanager get A进入休眠状态时,hibernate抛出一个 org.hibernate.exception.ConstraintViolationException ,该对象应添加到添加的新B''实例中到A。
我认为问题与更改实例A'的删除方法有关,因此无法重新加载A。但是如何重新加载A的新状态? 请在下面看看:
@Transactional
public void compeleteSomething(
@NonNull String location,
@NonNull String nameOfA) throws SomeException{
A a= serviceOfA.get(nameOfA);
B b= a.getB();
someService.removeBAndLinkToA(b.getId()); // <-- maybe here is the error
B newInstanceOfB = someService.createBOn(location);
someService.setBonA(serviceOfA.get(nameOfA), newInstanceOfB); // <-- serviceOfA.get() throws error
[...]
}
这里是 someService.removeBAndLinkToA(#)
的方法@Transactional
public void removeBAndLinkToA(
@NonNull Long id) {
B b = serviceOfB.get(id);
A a = b.getA();
if (a!= null) {
a.setB(null);
serviceOfA.save(a); // <-- This should cause the error?
}
serviceOfB.delete(b);
}
如何避免此问题? 非常感谢!
答案 0 :(得分:1)
在事务内部工作时,如果实体管理器注入了适当的作用域,则它应处理所有冲突直到提交为止。您无需在每个步骤中保存实体,也无需从数据库中再次检索它:它的状态由Entitymanager管理(不需要双关语)。
简而言之,您的completeSomething方法不需要调用其他服务方法。只需使b.setA(null),a.setB(new B())并返回即可。一切都会按预期进行:
@Transactional
public void completeSomething(String aId) {
A a = entityManager.find(A.class, aId);
B b = a.getB();
a.setB(new B());
b.setA(null);
} // container should end transaction here, commiting changes to entities
如果事务成功,则只要@PersistenceContext具有PersistenceContextType.TRANSACTION类型(默认设置),容器将对实体提交更改,并且更改将反映在数据库中。