首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

JPA持久化有关问题

2012-08-28 
JPA持久化问题在我的一个JBOSS应用服务器里,有这样三个EJB?@Local({B.class})@Remote({B.class})public BI

JPA持久化问题

在我的一个JBOSS应用服务器里,有这样三个EJB

?

@Local({B.class})@Remote({B.class})public BImpl implements B{    @PersistenceContext    protected EntityManager entityManager;    public T find(Long id){        return entityManager.find(T.class,id);    }    public void delete(T entity){        system.out.println(entityManager.contains(entity));        entityManager.remove(entity);    }}

?

其中ABean,BImpl是无状态会话Bean,都有业务接口分别为A和B。另外T为实体Bean。使用了CMT, 只使用了一个数据源。

?

远程客户端通过JNDI获取A的引用后,调用A.a()方法,最后是报出了异常的,异常原因是“试图删除一个脱管(detached)实体”,而且system.out.println(entityManager.contains(entity))输出是false,即证明了所传给B.delete方法的实体是一个已经脱管的EntityBean;

?

后来对ABean进行了修改,对于ABean中的B接口不利用@EJB来进行容器注入,而是通过JNDI来查找本地接口引用,这个时候,执行A.a()方法是可行的,没有报错,而且system.out.println(entityManager.contains(entity))输出是true,即证明了所传给B.delete方法的实体是一个还受容器管理的受管EntityBean;

?

但是如果ABean中的B接口通过JNDI来查找的不是本地接口,而是远程接口的时候,执行A.a()方法还是会报错的,错误原因还是因为“试图删除一个脱管(detached)实体”,system.out.println(entityManager.contains(entity))输出还是false。

?

通过对上面的实验,可以得出的结论是通过JNDI查找的远程接口中方法所返回的EntityBean是脱管的,而通过JNDI查找的本地接口中方法所返回的EntityBean是受管的。这个可以理解。但是为什么通过@EJB利用容器注入的接口所返回的EntityBean是脱管的?这个真的是无法解释,我也不清楚为什么

?

下面是从网上找到的一些概念

?

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

一个持久化上下文与一个事务上下文是松耦合的;严格的讲,它隐含的与一个事务会话共存。

?

EntityManager

实体对象由实体管理器进行管理,通过EntityManager和持久化上下文进行交互

实体管理器有两种:

容器类:容器型的实体管理器由容器负责试题管理器之间的协作,Java EE应用服务器提供的就是管理型的实体管理器。

应用程序型:实体管理器的生命周期由应用程序控制,应用程序通过javax.persistence.EntityManagerFactoty的creaeEntityManager创建EntityManager实例

?

如果使用事务范围的容器管理的实体管理器,那么提交事务、回滚事务、清除持久化上下文、关闭实体管理器、以及序列化实体或按值传递一个实体(如在分布式应用中,通过远程接口传递等)都会产生脱管实体。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

?

其实依赖注入只工作在本地命名服务中,不能注入远程服务器的对象。在实际应用中,EJB可能会使用到其他EJB或资源,这时必须通过JNDI查找或注入注释。因些上面通过@EJB来注入接口存根的话,应该是本地的才对,但是结果却跟通过JNDI获取到的本地接口执行结果不一样,真是不清楚怎么回事了。

?

?

?

?

热点排行