在同一事务中同步更改的实体
Synchronize changed entities in the same transaction
我对更改实体并希望以其他方式更新它的事务方法有疑问。
起初我使用实体管理器方法 "get" 从数据库中获取实体 A。
然后我得到一个相关实体 B 其中 A 到 B 是一对一的类型(可选)。 (所以 B 的 id 字段在 A 的 table 里面)。现在我想通过服务方法删除实体 B。因此我必须使用 B.
的 ID
在服务方法 i get 中从实体管理器(现在是 B')获取 B。然后我从获得的B'得到A'。然后,当它通过 A'.setB(null ) 后跟 serviceOfA.save(A').
然后我通过 serviceOfB.delete(B') 删除 B'。
当完成通过 id 删除 B 的方法后,我想更改实例 A 的属性。
例如,创建 B 的另一个实例。现在,当我再次通过实体管理器 get A 时,hibernate 会为应该添加到新 B 的对象抛出 org.hibernate.exception.ConstraintViolationException''添加到 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);
}
我怎样才能避免这个问题?
非常感谢!
在事务内部工作时,entitymanager 应该处理所有关系直到提交,前提是它被注入了适当的范围。您不需要在每一步都保存实体,也不需要从数据库中再次检索它:它的状态由 entitymanager 管理(没有双关语意)。
简而言之,您的 completeSomething 方法不需要调用另一个服务方法。只需制作 b.setA(null)、a.setB(new B()) 和 return。一切都应该按预期工作:
@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 类型(默认类型),更改就会反映在数据库中。
我对更改实体并希望以其他方式更新它的事务方法有疑问。
起初我使用实体管理器方法 "get" 从数据库中获取实体 A。 然后我得到一个相关实体 B 其中 A 到 B 是一对一的类型(可选)。 (所以 B 的 id 字段在 A 的 table 里面)。现在我想通过服务方法删除实体 B。因此我必须使用 B.
的 ID在服务方法 i get 中从实体管理器(现在是 B')获取 B。然后我从获得的B'得到A'。然后,当它通过 A'.setB(null ) 后跟 serviceOfA.save(A').
然后我通过 serviceOfB.delete(B') 删除 B'。
当完成通过 id 删除 B 的方法后,我想更改实例 A 的属性。 例如,创建 B 的另一个实例。现在,当我再次通过实体管理器 get A 时,hibernate 会为应该添加到新 B 的对象抛出 org.hibernate.exception.ConstraintViolationException''添加到 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);
}
我怎样才能避免这个问题? 非常感谢!
在事务内部工作时,entitymanager 应该处理所有关系直到提交,前提是它被注入了适当的范围。您不需要在每一步都保存实体,也不需要从数据库中再次检索它:它的状态由 entitymanager 管理(没有双关语意)。
简而言之,您的 completeSomething 方法不需要调用另一个服务方法。只需制作 b.setA(null)、a.setB(new B()) 和 return。一切都应该按预期工作:
@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 类型(默认类型),更改就会反映在数据库中。