一个实体从创建到销毁经历的几个状态:
瞬时状态(transient)----持久化状态(Persisted)-----托管状态(Managed/Attached)-----游离状态(Detached)-----销毁状态(Removed)
1.瞬时状态(transient):
只是new,但是还没persist到数据库,只是在内存当中。
2.持久化状态(Persisted):
已经persist到数据库中
3.托管状态(Managed/Attached):
实体处于持久化上下文当中。将实体转为托管状态的方法:
(1)调用persist(),实体从瞬时状态到托管状态到持久化状态
(2)调用find()或Query执行查询:实体从持久化状态到托管状态
(3)调用refresh():将游离状态的实体重新装载,并转为托管状态
(4) 调用merge():将游离状态的实体转变为托管状态
4.游离状态(Detached):
实体不在持久化上下文当中。它的属性与数据库中的不同步。
实体有托管状态到游离状态:
(1)一个事务结束,实体超出持久上下文的作用域,变为游离状态。对于无状态的session bean,通常一个方法作为一个持久化上下文的作用域。
(2)当复制实体对象或序列化时,实体将转变为游离状态。通常序列化对象发送在远程调用session bean时。
(3)调用clear()方法时,所有的实体将强制转化为游离状态。
5.销毁状态(Removed):
实体从数据库中删除后的状态。
em.remove(customer);
实体必须在托管状态下被删除。
@PersistenceContext protected EntityManager em; public void deleteCustomer(Integer customerId){ Customer customer=em.find(Customer.class,customerId); em.remove(customer); } //对比这两个删除方法的不同: @PersistenceContext protected EntityManager em; public void deleteCustomer(Customer customer){ //将游离状态的customer实体对象变为托管状态 customer=em.merge(customer); //删除实体 em.remove(customer); }
对于第二个方法,如果没有用merge()将游离状态的实体转变为托管状态,而直接remove()则会抛出异常。
---------------------------------------------------------------------
实体状态分析:
1.在客户端通过new方式获得的实体是瞬时状态;通过find方法获得的,由于经过序列化,它的状态是游离的。
2.当调用session bean的方法后,进入了EJB的事务管理单元(这里默认事务管理单元为一个EJB方法),这时就进入到了持久化上下文的作用域中
3.在持久化上下文当中,通过find方法获得一个托管状态的实体;通过merge方法将游离的实体转化为托管状态;通过persist方法持久化实体。
4.EJB方法结束,超出持久化上下文的作用域,此时返回的实体类将重新回到游离状态。