在我的 DAO 类中,我引用了 EntityManager。我想通过使用 ThreadLocal 使对 EntityManager 的访问成为线程安全的。
到目前为止,我的尝试仅导致了 NullPointerException,而且我似乎找不到合适的示例。
有人可以给我举个例子或者指出我正确的方向吗?
更新:我已经尝试过BalusC的建议,但是当我同时通过JSF和JAX-RS Web服务访问DAO时,我仍然收到错误:
org.hibernate.exception.GenericJDBCException: could not load an entity
java.sql.SQLException: You can't operate on a closed Connection!!!
java.lang.NullPointerException
at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement
我正在使用C3P0,所以我不知道为什么关闭连接会出现问题。
update2:BalusC 的最后一条评论似乎解决了我的问题:至少,您不应该在整个应用程序中共享 DAO 类的单个实例。根据每个请求创建一个新的。
In my DAO
classes I have a reference to an EntityManager
. I want to make the acces to the EntityManager
thread-safe by using ThreadLocal
.
So far my attempts have only resulted in NullPointerException
s, and I can't seem to find a decent example.
Can someone provide me with an example or point me in the right direction?
update: I've tried BalusC's suggestion, but when I acces the DAO through JSF and the JAX-RS webservice at the same time, I'm still getting errors:
org.hibernate.exception.GenericJDBCException: could not load an entity
java.sql.SQLException: You can't operate on a closed Connection!!!
java.lang.NullPointerException
at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement
I'm using C3P0, so I don't know why a closed connection is a problem.
update2: BalusC's last comment seemed to have solved my problem: At least, you should not have a single instance of the DAO class shared throughout the application. Create a new one on every request.
发布评论
评论(2)
不要这样做。让容器来操心这个事情吧。我会让你的 DAO 成为
@Stateless
EJB 并使用@PersistenceContext
注入EntityManager
。例如,要将其注入 JSF 托管 bean 或 JAX-RS 服务中,只需使用
@EJB
:要控制事务级别,请使用
@TransactionAttribute
注释(默认为TransactionAttributeType#REQUIRED
)。Don't do that. Let the container worry about this. I'd make your DAOs a
@Stateless
EJB and use@PersistenceContext
to inject theEntityManager
. E.g.To inject it in your JSF managed beans or JAX-RS services, just use
@EJB
:To control the transaction level, use
@TransactionAttribute
annotation (which defaults toTransactionAttributeType#REQUIRED
).当您不在 EJB 应用程序服务器中时,为什么要尝试 CDI 注入 EntityManger?只需使用 javax.persistence.Persistence 和持久性单元的名称来获取 EntityManagerFactory,然后使用 EMF 来获取 EntityManager,就像在servlet 中一样。使用数据库事务锁来确保对数据库的一致并行访问,不要在java代码中使EntityManager“线程”安全。
Why are you tring to CDI inject your EntityManger when you're not in an EJB app server? Just Grab a hold of your EntityManagerFactory using javax.persistence.Persistence and the name of your persistence unit, then with the EMF get a hold of your EntityManager(s) like in a servelet and what not. Use data base transaction locks to ensure consistem parallel access to the db, don't go around making EntityManager "thread" safe in java code.