我正在使用CMT和无状态EJB。假设我有两个方法,其中一个是EJB计时器的超时,另一个是修改现有实体的方法:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Timeout
public void cullOldEntities() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaDelete<T> cd = cb.createCriteriaDelete(clazz);
Root<T> root = cd.from(clazz);
Path<Date> dateCreatedPath = root.get("lastUpdated");
cd.where(cb.lessThan(dateCreatedPath, dateOfExpiry()));
em.createQuery(cd).executeUpdate();
}
public void modifyEntities(...)
由于cullOldEntities需要新事务,因此会创建新的持久性上下文,然后在方法结束时提交。问题是另一个事务的预先存在的持久化上下文会发生什么。
如果调用了modifyEntities,然后调用了cullOldEntities,那么如果cullOldEntities首先完成并且持久化上下文已经提交,它们会同时运行modifyEntities持久化上下文吗?
modifyEntities的持久性上下文是否与所做的更改同步?
如果没有修改实体会发生什么?
如何通过并发修改进行批量删除?
答案 0 :(得分:0)
EntityManager不是线程安全的。因此,如果没有锁定,则最后一次提交将覆盖在另一个事务中进行的更改。
答案 1 :(得分:0)
行为(以及对事务传播设计的后续影响)取决于用于持久性上下文的作用域的类型。这两种是Transaction scoped
和Extended Persistence context
(可以跨越多个事务)。对于事务范围的持久性上下文 - 在cullOldEntities()
方法调用开始之前,
容器将暂停继承的事务(如果有)并将启动新事务
事务(因为属性TransactionAttributeType.REQUIRES_NEW)。当在实体管理器上调用需要事务的实体管理器方法时,它将检查当前事务的活动持久性上下文,并且不会找到任何事务管理器。一个新的
将从该调用开始创建持久化上下文,并且此持久性上下文将是
活动持久性直到方法contextcullOldEntities()结束。因为交易
在cullOldities开始()与前一个(如果有的话)不同,由前一个持久化上下文管理的实体
这个新的不可见。
然而,扩展持久化上下文通常作用于绑定到它的有状态会话bean。 有状态会话bean的扩展实体管理器始终使用相同的持久性 上下文。有状态会话bean与单个扩展持久性上下文相关联 在创建bean实例时创建,并在删除bean实例时关闭。