事务提交后未刷新更新查询

Update query not flushed after transaction commit

我有几个扩展 BaseRepository 的存储库,如下所示:

public abstract class IsoRepository<T extends Serializable> {
    @PersistenceContext
    protected EntityManager entityManager;

    public void persist(T obj) {
        entityManager.persist(obj);
    }
}

@Stateless
public class T1Repository extends BaseRepository<T1> {
    // methods depending on repository
}

@Stateless
public class T2Repository extends BaseRepository<T2> {
    public Optional<T2> findByOrderId(String id) {
        return entityManager.createNamedQuery(/* ... */, T2.class)
            .setParameter("id", id).getResultList().stream().findFirst();
    }
}

// and others

EJB bean 包含负责保存事务的方法:

@Stateless
public class TransactionService {
    @EJB
    private T2Repository t2Repository;

    public void saveTransaction() {
        // Here occurs logic that saves new entities to database via repositories injected with EJB annotation
        // and also as the last operation update is performed:
        T2 t2 = t2Repository.findById(id);
        t2.setProperty(someProperty);
        t2Repository.persist(t2);
    }
}

问题是所有插入查询都保存在数据库中,但不是这个糟糕的更新。我发现我需要显式调用 entityManager.flush(),因为它似乎可以解决问题,但我真的不明白为什么会这样。我一直认为在事务提交后所有数据都会自动刷新。我是否更改了配置中的某些内容?

根据 JPA 文档

"persist(Object entity)
Make an instance managed and persistent." 

表示,persist只能用于插入。通常你应该得到

"EntityExistsException - if the entity already exists. 
(If the entity already exists, the EntityExistsException may be 
thrown when the persist operation is invoked, or the 
EntityExistsException or another PersistenceException may be thrown at 
flush or commit time.)"

如文档所述。所以:

    T2 t2 = t2Repository.findById(id);
    t2.setProperty(someProperty);
    t2Repository.persist(t2);

根据 JPA 定义,在任何情况下都应立即或在事务结束时导致 EntityExistsException。此结束也可以在本身调用 TransactionService.persist 的方法的末尾。 在任何情况下,此异常都应导致回滚,因此您的更新将永远不会完成。

我的推荐:

摆脱持久化调用,因为对象在查找过程中被管理,更改将在事务结束时完成。

参见:does-jpa-hibernate-save-even-when-not-calling-persist