根据EntityManager 对象的管理方式,可以有以下两种类型。
— 容器托管的(container-managed )EntityManager 对象
容器托管的EntityManager 对象最简单,程序员不需要考虑EntityManager 连接的释放,以及事务等复杂的问题,所有这些都交给容器去管理。容器托管的EntityManager 对象必须在EJB容器中运行,而不能在Web容器和J2SE的环境中运行。本书前面讲述的EntityManager 对象都是通过注入 @PersistenceContext注释来获得的,其实,这种获得EntityManager 对象的方式就是容器托管的。
— 应用托管的(application-managed)EntityManager 对象
应用托管的EntityManager 对象,程序员需要手动地控制它的释放和连接、手动地控制事务等。但这种获得应用托管的EntityManager 对象的方式,不仅可以在EJB容器中应用,也可以使 JPA 脱离EJB容器,而与任何的Java环境集成,比如说Web容器、J2SE环境等。所以从某种角度上来说,这种方式是JPA 能够独立于EJB环境运行的基础。
理想状态下,最好是选用容器托管的EntityManager 对象的方式,但在特殊的环境下,还是需要使用应用托管的EntityManager 对象这种方式。
应用程序管理的EntityManager (Application-Managed EntityManager )
Ø 就持久化上下文而言,应用程序管理的EntityManager 就像扩展的容器管理的EntityManager 。当创建应用程序管理的EntityManager 实例之后,该EntityManager 实例立即创建一个属于它自己私有的持久化上下文,该持久化上下文将一直存活下去,直到所属的EntityManager 实例销毁才消失。
如果使用spring3框架,那么就可以使用spring提供的容器托管方式+spring annotation transaction,使用上非常简单。但是在GAE环境下,就会造成启动时间过长。如果程序访问不频繁的话,单次访问时间很长。
GAE提供了应用程序管理的模式。这里需要考虑的是entityManager的创建和传递问题。
如果我们用dao class来管理具体的原子操作, 用service类来调用dao,service类来管理transaction,entityManager可以有如下的创建方式:
1。如果service, dao都是每次重新创建的,那么可以通过filter从外部创建entityManager,然后传递到service, dao当中。
2。如果希望service是单例,那么就要考虑service的线程安全性。一种方法是每个service方法创建entityManager,创建transaction, 新建dao并传递entityManager; 另一种方法就是通过threadLocal变量与单例的dao进行变量传递。
see more on http://open-open2009.iteye.com/blog/530843