改章节笔者在北京喝咖啡的时候突然想到的...近期就有想写几篇关于事务persistence的博客,所以回家到以后就奋笔疾书的写出来发布了
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三者的关系
1、EntityManager和EntityManagerFactory
EntityManager称为实体管理器,它由EntityManagerFactory所创立。EntityManagerFactory,作为EntityManager的工厂,包含有当前O-R映射的元数据信息,每一个EntityManagerFactory,可称为一个持久化单元(PersistenceUnit),每一个持久化单元可认为是一个数据源的映射(所谓数据源,可理解为一个数据库,我们可以在应用服务器中配置多个数据源,同时使用不同的PersistenceUnit来映射这些数据源,从而可以很方便的实现逾越多个数据库之间的事务操作!)
2、EntityManager和PersistenceContext
PersistenceContext,称为持久化上下文,它一般包含有当前事务范围内的,被管理的实体对象(Entity)的数据。每一个EntityManager,都会跟一个PersistenceContext相关联。PersistenceContext中存储的是实体对象的数据,而关系数据库中存储的是记录。
EntityManager正是维护这种OR映射的中间者,它可以把数据从数据库中加载到PersistenceContext中,也可以把数据从PersistenceContext中持久化到数据库。
EntityManager是应用程序操纵持久化数据的接口,EntityManager的接口方法有:
Persist、merge、remove、refresh、flush,
通过这些接口操纵PersistenceContext中的实体对象与数据库数据之间的同步!
这里又牵扯到一个实体对象的生命周期的概念
(1)几种状态
New–即未有id值,还没有跟persistence context建立关联的对象
Managed–有id值,已跟persistence context建立了关联
Detached–有id值,但没有(或不再)跟persistence context建立关联
Removed–有id值,而且跟persistence context尚有关联,但已准备好要从数据库中把它删除。
(2)与EntityManager接口的关系
小小结:EntityManager的作用与hibernate session类似。为了可以在一个请求周期中使用同一个session对象,在hibernate的解决方案中,提出了currentSession的概念,hibernate中的current session,可以跟JTA事务绑定,也可以跟当前线程绑定。在hibernate中,session管理着全部的持久化对象的数据。而在EJB3中,EntityManager管理着PersistenceContext,PersistenceContext正是被管理的持久化对象的集合。
二、EntityManager的管理方法分为两种:
1、容器管理的EntityManager– 通过PersistenceContext注入EntityManager对象,或通过jndi查询到EntityManager
定义方法:
@PersistenceContext(name="test")
private EntityManager em;
容器管理的EntityManager ,它所管理的PersistenceContext的生命周期由PersistenceContextType来配置
(1)Transaction-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 unit的EntityManager将使用一样的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共享!这个创立进程可以由EntityManagerFactory的createEntityManager方法来创立,通过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底层的事务实现可以使用JTA或RESOURCE_LOCAL类型的事务控制策略。
1、JTA和RESOURCE_LOCAL的区分
(1)JTA一般在容器环境中使用,而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">
(2)Container-Managed EntityManager必须是JTA类型的EntityManager,而Application-Managed EntityManager则既可以是JTA类型的EntityManager,也可以是RESOURCE_LOCAL类型的EntityManager。
2、JTA事务与普通JDBC事务的区分
(1)JDBC事务,一般由数据库本身来执行提交或回滚操作(单阶段提交)。全部数据库都有自己的事务管理器,管理执行的日记,这些管理器只能处置其自身的事务,称为本地事务。
(2)JTA支撑多个数据源,站在更高的角度上,供给一个“事务处置监听器(TPM)”来管理和协调这些数据源之间的事务操作,它必须执行两阶段提交协议(2PC)。
1)准备阶段-TPM向全部RM(资源管理器,即数据库)确认状态,是否可以提交或回滚。
2)提交阶段-TPM确认提交以后,向全部RM发出提交指令或回滚指令
TPM本身会维护事务日记,以保障持久性或灾难恢复等。
文章结束给大家分享下程序员的一些笑话语录: IT业众生相
第一级:神人,天资过人而又是技术狂热者同时还拥有过人的商业头脑,高瞻远瞩,技术过人,大器也。如丁磊,求伯君。
第二级:高人,有天赋,技术过人但没有过人的商业头脑,通常此类人不是顶尖黑客就是技术总监之流。
第三级:牛人,技术精湛,熟悉行业知识,敢于创新,有自己的公司和软件产品。
第四级:工头,技术精湛,有领导团队的能力,此类人大公司项目经理居多。
第五级:技术工人,技术精湛,熟悉行业知识但领导能力欠加,此类人大多为系分人员或资深程序员,基本上桀骜不逊,自视清高,不愿于一般技术人员为伍,在论坛上基本以高手面目出现。
第六级:熟练工人,技术有广度无深度,喜欢钻研但浅尝辄止。此类人大多为老程序员,其中一部分喜欢利用工具去查找网上有漏洞的服务器,干点坏事以获取成绩感。如果心情好,在论坛上他们会回答菜鸟的大部分问题。此级别为软件业苦力的重要组成部分。
第七级:工人,某些技术较熟练但缺乏深度和广度,此类人大多为程序员级别,经常在论坛上提问偶尔也回答菜鸟的问题。为软件产业苦力的主要组成部分。
第八级:菜鸟,入门时间不长,在论坛上会反复提问很初级的问题,有一种唐僧的精神。虽然招人烦但基本很可爱。只要认真钻研,一两年后就能升级到上一层。
第九级:大忽悠,利用中国教育的弊病,顶着一顶高学历的帽子,在小公司里混个软件部经理,设计不行,代码不行,只会胡乱支配下属,拍领导马屁,在领导面前胡吹海侃,把自己打扮成技术高手的模样。把勾心斗角的办公室文化引入技术部门,实在龌龊!
第十级:驴或傻X,会写SELECT语句就说自己精通ORALCE,连寄存器有几种都不知道就说自己懂汇编,建议全部送到日本当IT产业工人,挣了日本人的钱还严重打击日本的软件业!
--------------------------------- 原创文章 By
事务和persistence
---------------------------------