JPA技术简单介绍
什么是JPA?JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE5规范中提出的Java持久化接口。JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。使用JPA持久化对象,并不是依赖于某一个ORM框架。
为什么要使用JAP?在说为什么要使用JPA之前,我们有必要了解为什么要使用ORM技术。
ORM是Object-Relation-Mapping,即对象关系影射技术,是对象持久化的核心。ORM是对JDBC的封装,从而解决了JDBC的各种存在问题:
a) 繁琐的代码问题
用JDBC的API编程访问数据库,代码量较大,特别是访问字段较多的表的时候,代码显得繁琐、累赘,容易出错。例如:PreparedStatementpstmt=con.prepareStatment("insert into accountvalue(?,?,?,?,?,?,?,?,?)");
ORM则建立了Java对象与数据库对象之间的影射关系,程序员不需要编写复杂的SQL语句,直接操作Java对象即可,从而大大降低了代码量,也使程序员更加专注于业务逻辑的实现。
b) 数据库对象连接问题
关系数据对象之间,存在各种关系,包括1对1、1对多、多对1、多对多、级联等。在数据库对象更新的时候,采用JDBC编程,必须十分小心处理这些关系,以保证维持这些关系不会出现错误,而这个过程是一个很费时费力的过程。
ORM建立Java对象与数据库对象关系影射的同时,也自动根据数据库对象之间的关系创建Java对象的关系,并且提供了维持这些关系完整、有效的机制。
c) 系统架构问题
JDBC属于数据访问层,但是使用JDBC编程时,必须知道后台是用什么数据库、有哪些表、各个表有有哪些字段、各个字段的类型是什么、表与表之间什么关系、创建了什么索引等等与后台数据库相关的详细信息。
使用ORM技术,可以将数据库层完全隐蔽,呈献给程序员的只有Java的对象,程序员只需要根据业务逻辑的需要调用Java对象的Getter和Setter方法,即可实现对后台数据库的操作,程序员不必知道后台采用什么数据库、有哪些表、有什么字段、表与表之间有什么关系。
d) 性能问题
采用JDBC编程,在很多时候存在效率低下的问题。
pstmt =conn.prepareStatement("insert into user_infovalues(?,?)");
for(inti=0;i<1000;i++){
pstmt.setInt(1,i);
pstmt.setString(2,"User"+i.toString());
pstmt.executeUpdate();
}以上程序将向后台数据库发送1000次SQL语句执行请求,运行效率较低。
采用ORM技术,ORM框架将根据具体数据库操作需要,会自动延迟向后台数据库发送SQL请求,ORM也可以根据实际情况,将数据库访问操作合成,尽量减少不必要的数据库操作请求。
JPA是目前比较流行的一种ORM技术之一,所以他拥有ORM技术的各种特点,当然他还有自己的一些优势:
1 标准化
JPA是JCP组织发布的JavaEE标准之一,因此任何声称符合JPA标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
2对容器级特性的支持
JPA框架中支持大数据集、事务、并发等容器级事务,这使得JPA超越了简单持久化框架的局限,在企业应用发挥更大的作用。
3简单易用,集成方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java类一样简单,没有任何的约束和限制,只需要使用javax.persistence.Entity进行注释;JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
4可媲美JDBC的查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是HibernateHQL的等价物。JPA定义了独特的JPQL(JavaPersistenceQueryLanguage),JPQL是EJBQL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUPBY、HAVING等通常只有SQL才能够提供的高级查询特性,甚至还能够支持子查询。
5支持面向对象的高级特性
JPA中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。怎么使用JPA?简单说来要使用JPA需要网工程里面导入jar包(不同的提供商提供的jar包也不同),并且还要有一个persistence.xml文件来设置持久性单元。
如果你打算在你的应用中使用JPA,你就需要使用持久性单元(PersistenceUnits)。持久性单元具有唯一的名称,负责定义应用中的一组实体如何进行管理和持久性。在应用中使用persistence.xml文件来设置持久性单元,可以配置多个持久性单元,但每个单元拥有唯一的名称。
注意:persistence.xml文件的位置决定持久性的根(PersistenceRoot)。持久性的根为JAR文件或者包含META-INF目录(前提是persistence.xml位于此)的目录。一般将这个persistence.xml文件放在src下的META-INF中。
持久性单元包含的属性有:
在该持久性单元范围(作用域)内的实体类
为上述实体类提供持久性的持久性提供者(PersistenceProvider)或库
上述实体类的数据源(DataSource)
应用使用的事务类型(TransactionType)
持久性提供者(Persistence Provider)持久性提供者指的是JPA的实现。持久性提供者是一个能够为应用提供持久性对象的的库。例如Netbeans绑定了TopLinkEssentials 作为持久性提供者,同时TopLink Essentials也是Sun Java SystemApplication Server Platform Edition 9 (Glassfish)的参考实现和默认配置。TopLinkEssentials包括toplink-essentials.jar和toplink-essentials-agent.jar两个JAR文件。你可以使用别的持久性提供者例如Hibernate。
数据源
数据源指的是提供实体存储的数据库。数据源必须在服务器中注册并且使用JNDI名称指定。如果事务是由容器管理的JTA事务那么数据源必须是JTA数据源。如果事务是应用负责管理的,数据源根据在IDE中注册的JDBC数据库连接指定。
在Java SE环境下,数据库可以通过数据源指定,也可以使用其他方法,取决于持久性提供者的要求。
事务类型
持久性单元指定事务是如何管理的。事务类型取决于目标容器,如果目标容器是JavaEE容器,你可以使用容器管理或者应用管理。如果不是这样的话,你只能使用应用管理。
容器管理的事务(JTA事务)
容器使用JavaTransactionAPI来管理事务。你必须将你的应用部署在JavaEE容器中,并且你的数据源必须支持JTA。
在persistence.xml中事务类型被设置为JTA.如果你使用Glassfish这个是默认选项。应用管理的事务(本地资源事务:Resource-Local Transaction)由应用负责事务处理。在persistence.xml文件中,被设置为RESOUCE_LOCAL
一个简单的persistence.xml配置文件例子:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="lite_db_pu" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>com.e.liteworkflow.entity.Workflow</class> <class>com.e.liteworkflow.entity.Activity</class> <properties> <property name="toplink.jdbc.user" value="sa"/> <property name="toplink.jdbc.password" value="E2005"/> <property name="toplink.jdbc.url" value="jdbc:jtds:sqlserver://10.30.20.69/liteworkflowdb"/> <property name="toplink.jdbc.driver" value="net.sourceforge.jtds.jdbc.Driver"/> <!--property name="toplink.logging.level" value="FINE"/--> <property name="toplink.ddl-generation" value="create-tables"/> <property name="toplink.weaving" value="false"/> </properties> </persistence-unit> <persistence-unit name="lite_derby_pu" transaction-type="RESOURCE_LOCAL"> <!— 省略了配置内容 --> </persistence-unit> </persistence>
对配置文件中一些重要元素和属性的解释:
1.配置文件中可以有多个<persistence-unit></persistence-unit>但是这些persistence-unit的name属性不可以相同;
2.persistence-unit的transaction-type标明了事务由谁去管理,RESOURCE_LOCAL指本地数据库管理事务(不支持分布式事务),而JTA则是由托管的容器来管理事务(支持分布式事务);
3.<provider></provider>声明了类文件,这个类文件提供初始的factory方法来创建一个EntityManager实例;
4.<class></class>列出应用程序中的实体类的名称(这里要有完整的包名和类名);
5.<properties></properties>中的<property/>均是设置连接数据库的相关信息:
属性名:toplink.weaving
描述:是否加载实体使用织入,如果对@OneToOne和@ManyToOne的关系实体使用惰性加载,则必须使用织入的方式。
可选值:true(默认):织入实体。
false:不织入实体。
static:静态织入实体,如果运行在不是Java EE 5容器中,或者JDK 不支持代理
-javaagent:toplink-essentials-agent.jar方式运行时,需要设置此选项。
属性名:toplink.ddl-generation
描述:指定DDL生成方式,这些值定义在cle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider类中。
可选值:none(默认):不生成DDL,不自动生成数据库。
create-tables:只生成不存在的表,不改变原有表结构。
(create-tables属性值。如果表存在的话,代码执行结果就向存在的表格中插入记录,并且生成很多的警告信
息,告诉你存在了那些表)
drop-and-create-tables:删除原表,重新生成新表。
数据源的指定:根据自己的实现和应用服务器的默认行为,可能需要为jta-data-source(指定JTA数据源)和/或non-jta-data-source(指定非JTA数据源)设置提供值。