我正在维护一些运行正常的旧JEE代码,但是正在使用一些静态帮助器类,其中实体管理器从调用EJB的方法中传递,如下所示:
public class StaticHelper {
public static void helpingOut(EntityManager entityManager, String value) {
// i.e. insert value
}
}
由于这似乎不适合JEE并且对单元测试不好,我已经将这些助手转换为@Stateless
EJB,如下所示:
@Stateless
public class StatelessHelper {
@PersistenceContext(unitName="SuperUnit")
private EntityManager entityManager;
public void helpingOut(String value) {
// i.e. insert value
}
}
就像我可以使用CDI-Unit在调用EJB中注入一个模拟帮助器。
现在,根据负载,容器会创建1-3个无状态助手的实例,这根本不是问题,但无论如何,我想到@Singleton
使用@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
1}}或@Lock(LockType.READ)
使其成为多线程 - 但这似乎不是一个好主意,因为EntityManager
不是线程安全的。或者这explained here仍适用吗?
“...容器序列化对每个有状态和无状态的调用 会话bean实例。大多数容器将支持许多实例 会话bean并发执行;但是,每个实例都看到了 只是序列化的方法调用序列。因此,有状态或 无状态会话bean不必编码为可重入...“
答案 0 :(得分:0)
我创建了一个simple project来检查/测试容器如何处理SLSB
和Singleton
中的事务。我提到的案例是:
@PersistenceContext EntityManager
SLSB
@Datasource
SLSB
@Datasource
@Singleton
低于测试结论。
EntityManager
可靠。使用默认隔离级别,足以避免数据不一致。 OptimisticLockException
,因此我们将点重新发送到信息中心。 EnityManager
的{{1}}被容器注入到每个SLSB
个实例中。之后,EntityManager
负责数据一致性。SLSB
安全意味着容器一次只保证一个线程可以执行单个实例(但不同的实例在不同的线程中并发运行)< / LI>
@Singleton
。使用Lock.WRITE
,您可以将线程/实例之间的隔离级别增加到SERIALIZABLE
。@Singleton
的情况下,执行时间会随着客户端的增加而增加,因为每个客户端都会相互等待。对于100个客户端,第100个客户端将等待99 x 单个执行时间。 @Singleton
,则执行时间随着并发客户端数量的增加而增加。例如:如果100个客户端同时调用Singleton SLSB
,则最后一个客户端的执行时间为(99 x 执行时间)。 select ... for update
)中使用隔离级别。请参阅DashboardDSSelectForUpdate TransactionManagement(BEAN)
并更改连接的隔离级别,例如conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
请参阅:DashboardDSTxBean