JPA(Java Persistence API,Java持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。

JPA是JSR-220(EJB3.0)规范的一部分,在JSR-220中规定实体对象(EntityBean)由JPA进行支持。

所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行,开发和测试更加方便。

 

下面通过一张图来看一下JPA的基本概念。然后再做简要分析。

 

注:不是真正意义的UML图啊,只是画着方便就用rose了。

 

一、EntityManager,EntityManagerFactory,PersistenceContext三者的关系

1EntityManagerEntityManagerFactory

 

EntityManager称为实体管理器,它由EntityManagerFactory所创建。EntityManagerFactory,作为EntityManager的工厂,包含有当前O-R映射的元数据信息,每个EntityManagerFactory,可称为一个持久化单元(PersistenceUnit),每个持久化单元可认为是一个数据源的映射(所谓数据源,可理解为一个数据库,我们可以在应用服务器中配置多个数据源,同时使用不同的PersistenceUnit来映射这些数据源,从而能够很方便的实现跨越多个数据库之间的事务操作!)

 

2EntityManagerPersistenceContext 

 

PersistenceContext,称为持久化上下文,它一般包含有当前事务范围内的,被管理的实体对象(Entity)的数据。每个EntityManager,都会跟一个PersistenceContext相关联。PersistenceContext中存储的是实体对象的数据,而关系数据库中存储的是记录。

 

EntityManager正是维护这种OR映射的中间者,它可以把数据从数据库中加载到PersistenceContext中,也可以把数据从PersistenceContext中持久化到数据库。

EntityManager是应用程序操纵持久化数据的接口,EntityManager的接口方法有:

Persistmergeremoverefreshflush

通过这些接口操纵PersistenceContext中的实体对象与数据库数据之间的同步!

 

 

这里又牵扯到一个实体对象的生命周期的概念

1)几种状态

New即未有id值,尚未跟persistence context建立关联的对象

Managedid值,已跟persistence context建立了关联

Detachedid值,但没有(或不再)跟persistence context建立关联

Removedid值,而且跟persistence context尚有关联,但已准备好要从数据库中把它删除。

 

2)与EntityManager接口的关系

小小结:EntityManager的作用与hibernate session类似。为了能够在一个请求周期中使用同一个session对象,在hibernate的解决方案中,提出了currentSession的概念,hibernate中的current session,可以跟JTA事务绑定,也可以跟当前线程绑定。在hibernate中,session管理着所有的持久化对象的数据。而在EJB3中,EntityManager管理着PersistenceContextPersistenceContext正是被管理的持久化对象的集合。

 

 

二、EntityManager的管理方式分为两种:

 

1、容器管理的EntityManager– 通过PersistenceContext注入EntityManager对象,或通过jndi查询到EntityManager

定义方式:

@PersistenceContext(name="test")

private EntityManager em;

 

容器管理的EntityManager ,它所管理的PersistenceContext的生命周期由PersistenceContextType来配置

1Transaction-Scoped PersistenceContext – 由容器创建,随着Transaction而传播,随着Transaction的完成而销毁,对应用程序本身来说,它对persitence context的创建、销毁一无所知,完全自动和透明。当entity manager的方法被调用的时候,如果在当前JTA事务中还没有persistence context,那么将启动一个新的persistence context,并将它跟当前的JTA事务关联。

 

定义方式:

@PersistenceContext(unitName="myunit", type=PersistenceContextType.TRANSACTION)

private EntityManager em;

 

如:在Java EE环境下,一个JTA事务通常会横跨多个组件的调用(比如多个EJB组件的方法调用)。这些组件需要能够在单个事务范围内访问到同样的Persistence Context。为了满足这种情况的需要,当EntityManager被注入或通过jndi被查询的时候,它的Persistence Context将会在当前事务范围内自动传播,引用到同一个Persistence unitEntityManager将使用同样的Persistence Context。这可以避免在不同的组件之间传递EntityManager引用。

 

(2)Extended-Scoped PersistenceContext – 用于Stateful Session Bean,跨越多个Transaction,随着Stateful Session Bean的销毁而销毁,通常,这可以通过调用一个在stateful session bean中被注解定义为@Remove的方法来结束一个stateful session bean的生命周期。

 

@PersistenceContext(unitName="test", type=PersistenceContextType.EXTENDED)

private EntityManager em;

 

2、应用管理的EntityManager– 通过PersistenceUnit注入EntityManagerFactory对象

定义方式:

@PersistenceUnit(unitName="test")

private EntityManagerFactory factory;

 

应用程序自身需要独立访问Persistence Context。即每次创建一个EntityManager都会迫使创建一个新的Persistence Context。这些Persistence Context即使在同一个事务范围内也不会跟其它EntityManager共享!这个创建过程可以由EntityManagerFactorycreateEntityManager方法来创建,通过entityManager.close() / isOpen()方法来管理entityManager及其对应的persistence context.。这被称为应用管理的实体管理器(application-managed entity manager)。

 

定义方式:

@PersistenceUnit(unitName="test")

private EntityManagerFactory factory;

 

public void addStudent(String name) {

EntityManager em = factory.createEntityManager();

 

 

三、事务实现

EntityManager底层的事务实现可以使用JTARESOURCE_LOCAL类型的事务控制策略。

 

1JTARESOURCE_LOCAL的区别

1JTA一般在容器环境中使用,而RESOURCE_LOCAL一般在J2SE的环境下使用。

 

J2SE的环境下,由应用程序自身来创建EntityManagerFactory,并由EntityManagerFactory创建EntityManager,通过EntityManager.getTransaction.begin()方法来开启事务,commit()方法提交事务等等,这种方式就是RESOURCE_LOCAL的基本使用方法。

 

Persistence.XML配置示例:

<persistence-unit name="test" transaction-type="JTA">

 

JTA常在容器环境下使用,也就是使用JTA类型的EntityManager,这样,EntityManager的调用都是在一个外部的JTA事务环境下进行的,不用手动开启,提交事务等

 

Persistence.XML配置示例:

<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">

 

2Container-Managed EntityManager必须是JTA类型的EntityManager,而Application-Managed EntityManager则既可以是JTA类型的EntityManager,也可以是RESOURCE_LOCAL类型的EntityManager

 

 

2JTA事务与普通JDBC事务的区别

 

1JDBC事务,一般由数据库本身来执行提交或回滚操作(单阶段提交)。所有数据库都有自己的事务管理器,管理执行的日志,这些管理器只能处理其自身的事务,称为本地事务。

 

2JTA支持多个数据源,站在更高的角度上,提供一个“事务处理监听器(TPM)”来管理和协调这些数据源之间的事务操作,它必须执行两阶段提交协议(2PC)。

1)准备阶段-TPM向所有RM(资源管理器,即数据库)确认状态,是否可以提交或回滚。

2)提交阶段-TPM确认提交之后,向所有RM发出提交指令或回滚指令

 

TPM本身会维护事务日志,以保证持久性或灾难恢复等。

 

 

 

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐