DAO中的ThreadLocal JPA EntityManager

Sti*_*n.V 2 dao jpa entitymanager thread-local

在我的DAO课程中,我有一个参考EntityManager.我想EntityManager通过使用来访问线程安全的ThreadLocal.

到目前为止,我的尝试只导致了NullPointerExceptions,我似乎无法找到一个体面的例子.

有人可以给我一个例子或指出我正确的方向吗?

更新:我已经尝试过BalusC的建议,但是当我同时通过JSF和JAX-RS webservice访问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
Run Code Online (Sandbox Code Playgroud)

我正在使用C3P0,所以我不知道为什么闭合连接是个问题.

update2:BalusC的最后评论似乎解决了我的问题:At least, you should not have a single instance of the DAO class shared throughout the application. Create a new one on every request.

Bal*_*usC 5

我想EntityManager通过使用来访问线程安全的ThreadLocal.

不要那样做.让容器担心这一点.我会让您的DAO成为@StatelessEJB并用于@PersistenceContext注入EntityManager.例如

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public User find(Long id) {
        return em.find(User.class, id);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

要将其注入JSF托管bean或JAX-RS服务,只需使用@EJB:

@EJB
private UserService userService;
Run Code Online (Sandbox Code Playgroud)

要控制事务级别,请使用@TransactionAttribute注释(默认为TransactionAttributeType#REQUIRED).

  • 是的,这解释了它.配置中显然有些东西搞砸了.对不起,我没有手动丰富Tomcat和EJB/JPA支持的实践经验,所以我无法提供帮助.我所能做的就是建议您查看Glassfish Web Profile.所有人都会"只是"在没有太多小提琴的情况下解决问题.否则,好吧,也许只是放弃EJB的想法.至少,您不应该在整个应用程序中共享DAO类的单个实例.在每个请求上创建一个新的. (2认同)