在同一交易中同步更改的实体

时间:2020-04-27 08:51:17

标签: java hibernate jpa transactions java-ee-8

我对更改实体并想以其他方式更新它的事务处理方法有疑问。

首先,我使用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);
    }

如何避免此问题? 非常感谢!

1 个答案:

答案 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类型(默认设置),容器将对实体提交更改,并且更改将反映在数据库中。