当前位置:文档之家› JPA开发文档(大全)

JPA开发文档(大全)

JPA开发文档(大全)
JPA开发文档(大全)

JPA开发文档(大全)

这是一份比较全面的JPA文档,希望能够帮助大家,让大家更好的学习工作。

1.发展中的持久化技术3

JDBC (3)

关系对象映射(Object Relational Mapping,ORM) (3)

Java 数据对象(Java Data Object,JDO) (3)

Java Persistence API(JPA) (3)

2.JPA 体系架构 (5)

3.Entity Bean (7)

定义对Entity中属性变量的访问 (7)

主键和实体标识(Primary Key and Entity Identity) (9)

4.EntityManager (10)

配置和获得EntityManager (10)

Entity的生命周期和状态 (10)

持久化Entity(Persist) (11)

获取Entity (13)

更新Entity (13)

删除Entity (13)

脱离/附合(Detach/Merge) (14)

5.JPA Query (14)

Query接口 (15)

简单查询 (15)

使用参数查询 (16)

排序(order by) (16)

查询部分属性 (17)

查询中使用构造器(Constructor) (17)

聚合查询(Aggregation) (18)

关联(join) (19)

比较Entity (20)

批量更新(Batch Update) (21)

批量删除(Batch Remove) (21)

1.发展中的持久化技术

JDBC

很多企业应用的开发者选择使用 JDBC 管理关系型数据库中的数据。JDBC支持处理大量的数据,能够保证数据的一致性,支持信息的并发访问,提供 SQL 查询语言查找数据。JDBC 所使用的关系模型不是为保存对象而设计的,因此迫使开发者选择在处理持久数据时放弃面向对象编程,或者自己去开发将面向对象特性(比如:类之间的继承)和关系型数据库进行映射的专有解决方案。

关系对象映射(Object Relational Mapping,ORM)

ORM 是目前完成对象和关系数据表之间的映射最好的一种技术,这些 ORM 框架处理对象和关系数据库之间的协调工作,将开发者从这部分工作中解脱出来,集中精力处理对象模型。阻碍 ORM 发展的问题是,现有的每一种 ORM 产品都有自己特有的API,开发者只能将自己的代码绑定到某一个框架提供商的接口上,这种状况形成了厂商锁定,意味着一旦该框架提供商无法解决系统中出现的严重错误,或者因为其它的原因转而采用其它的框架,将会给开发者的企业应用带来极大的困难,唯一的解决办法是重写所有的持久化代码。

Java 数据对象(Java Data Object,JDO)

JDO 是 Java EE 标准中另外一个支持管理持久化数据的规范,JDO 规范使用和JPA 非常类似的 API,只是通常是通过 JCA 技术集成到应用服务器上。但是 JDO 是针对轻量级容器而设计的,不能够支持容器级别的声明式安全、事务特性,也无法对远程方法调用提供支持。

Java Persistence API(JPA)

EJB 规范由三部分组成: Simplified API、EJB 核心规范(EJB Core Contracts and Requirements)和 JPA(Java Persistence API)。JPA 规范部分详细的介绍了JPA 中实体 Bean 的定义,并介绍了实体 Bean 支持的注释、全新的查询语言、实体管理接口、容器实现规范等内容。

JPA 标准制定过程中充分吸收了目前已经出现的所有持久化技术的所有优点,摒弃了它们存在的局限,使 JPA 在简单易用、查询能力等方面表现突出。

标准化

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问 API,这保证了基于 JPA 开发的企业应用能够经过少量的修改就能够在不同的 JPA 框架下运行。

对容器级特性的支持

JPA 框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

简单易用,集成方便

JPA 的主要目标之一就是提供更加简单的编程模型:在 JPA 框架下创建实体和创建 Java 类一样简单,没有任何的约束和限制,只需要使用进行注释;JPA 的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA 基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。

可媲美 JDBC 的查询能力

JPA 定义了独特的 JPQL(Java Persistence Query Language),JPQL 是 EJB QL 的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

支持面向对象的高级特性

JPA 中能够支持面向对象的高级特性,比如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

表 1 持久化技术的优缺点

体系架构

JPA 中定义一套类和接口用于实现持久化管理和对象/关系的映射,下面这张图中显示了 JPA 的主要组件以及它们之间的相互关系。

图1 JPA 主要组件和相互关系

EntityManagerFactory

EntityManagerFactory 是 EntityManager 的工厂类,负责创建EntityManager 对象。

EntityManager

EntityManager 是 JPA 应用中使用的基本对象,通过它提供的相应方法可以管理持久化对象,也可以新建或者删除持久化对象。EntityManager 还负责创建 Query 实例。在容器外使用时,EntityManagerFactory 和 EntityManager 之间是一对一的关系。

Entity

EntityTransaction 提供 Entity 操作时需要的事务管理,和 EntityManager 是一对一的关系。在查询操作时不需要使用 EntityTransaction,而在对象持久化、状态更新、对象删除等情况下则必须使用显式的使用EntityTransaction 的相关方法管理事务。

Query

Query 是查询实体的接口,Query 对象可以从 EntityManager 中获得。根据

EJB 规范中的描述,Query 接口需要同时支持 JPQL 和原生态 SQL 两种语法。

Persistence

Persistence 是一个工具类,负责根据配置文件提供的参数创建EntityManagerFactory

对象。

下面的代码演示了如何通过 JPA 提供的接口和 JPQL 查询语言完成实体查询和

更新的例子,例子中的代码假定运行在非 Java EE 环境中。

清单 1 在非 Java EE 环境使用 JPA 接口的例子

EntityManagerFactory factory = (“mysql”);

*/

public HelloEntityBean() {

}

public int getId() {

return id;

}

采用access=PROPERTY(默认方式)时,元数据应该批注在对应属性变量的getter上。

private int id;

private String foo;

/**

* The entity class must have a no-arg constructor.

*/

public HelloEntityBean() {

}

@Id(generate=

public int getId() {

return id;

}

Entity类中的属性变量可以是以下数据类型:原始数据类型和他们的对象类型

byte[]

Byte[]

char[]

Character[]

enums

Entity类

嵌入实体类(embeddable classes)

还可以是以下集合类型:

和它的实体类

和它的实体类

和它的实体类

和它的实体类

主键和实体标识(Primary Key and Entity Identity)

每个Entity类都必须有一个主键。在EJB3中定义了两种主键:键单主键和复合主键。

简单主键必须对应Entity中的一个属性变量(Instance Variable),而该属性对应数据库表中的一列。使用简单主键,我们只需要用@Id元数据对一个属性变量或者她的getter方法进行批注。

当我们需要使用一个或多个属性变量(表中的一列或多列)联合起来作为主键,我们需要使用复合主键。复合主键要求我们编写一个复合主键类( Composite Primary Key Class )。复合主键类需要符合以下一些要求:

复合主键类必须是public和具备一个没有参数的constructor

复合主键类的每个属性变量必须有getter/setter,如果没有,每个属性变量则必须是public或者protected

复合主键类必须实现

复合主键类必须实现equals()和hashcode()方法

复合主键类中的主键属性变量的名字必须和对应的Entity中主键属性变量的名字相同

一旦主键值设定后,不要修改主键属性变量的值

复合主键的例子。Entity类Person,它的主键属性变量是firstName和lastName。

@Id

private String firstName;

@Id

private String lastName;

public Person() {

}

Person的复合主键类:

public class PersonPK implements

private String firstName;

private String lastName;

public PersonPK() {

}

public String getFirstName() {

return firstName;

}

public void setFirstName(String firstName) {

= firstName;

}

public String getLastName() {

return lastName;

}

public void setLastName(String lastName) {

= lastName;

}

}

对Entity进行操作的API都设计在接口上。EntityManager,顾名思义是管理所有EJB 3运行环境中的所有Entity。 EntityManager根据运行的环境不同分为容器管理的EntityManager和应用管理的EntityManager。

配置和获得EntityManager

在J2SE环境中,EJB3定义了一个类用于启动EJB3运行环境。要获得EntityManager,首先需要通过获得EntityManagerFactory,然后调用()方法获得。

当保存一个Entity时,以该对象为根对象的整个对象图都会自动的被保存。但在EJB3中,我们仍然可以通过关系元数据(比如OneToOne,OneToMany)的cascade属性来精确定义保存的级联行为。下面我们来看看不同的cascade属性的区别。

不配置cascade的情况下,EJB3 Persistence运行环境默认不会采用Persistence by reachability。

public class Father{

@Id

int id

String name;

egin;

Son mySon = new Son();

Father = new Father( 1, "father" mySon );

egin;

Son mySon = new Son();

Father = new Father( 1, mySon );

egin();

( father );

etParameter( 1, 2 );

oString() );

String customerName = row[1].toString();

String streetNumber = ( row[2].toString() );

查询中使用构造器(Constructor)

JPQL支持将查询的属性结果直接作为一个java class的构造器参数,并产生实体作为结果返回。

.from的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select语句中除了聚合函数外的所有属性。

// 返回所有的订单的生产厂商的的名字,货物号码和每种货物的订单价值总额

// 注意group by后面必须包含和

final Query query

= ( "select , , sum FROM Order o group by ,");

如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"WHERE"语句。

// 返回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单价值总额

// 这里"having = 'foo'为条件

final Query query

= ( "select , , sum FROM Order o

group by , having ='foo'");

在"HAVING"语句里可以跟"WHERE"语句一样使用参数。

// 返回所有的订单的生产厂商是"foo"的货物号码和每种货物的订单价值总额

// 这里"having = 'foo'为条件

final Query query

= ( "select , , sum FROM Order o

group by , having =1");

( 1, "foo" );

final List result = ();

关联(join)

在JPQL中,大部分的情况下,使用对象属性都隐含了关联(join)。例如在以下查询中:

final Query query = ( "select o from Order o where order by ");

当这个句JPQL编译成以下的SQL时就会自动包含了关联,JPQL编译成SQL时关联默认取左关联(left join)。

select , , , , ,

from orderTable as o left join addressTable where = 2000

但在一些情况下,我们仍然需要对关联做精确的控制。因此JPQL仍然支持和SQL 中类似的关联语法:

left out join/left join

inner join

left join/inner join fetch

left join, left out join等义,都是允许符合条件的右边表达式中的Entiies 为空。

// 返回所有地址为2000的Order纪录,不管Order中是否有OrderItem

final Query query = ( "select o from Order o left join where order by ");

由于JPQL默认采用left join。这样的查询和以下的JPQL其实是等价的。

// 返回所有地址为2000的Order纪录,不管Order中是否有OrderItem

final Query query = ( "select o from Order o where order by ");

需要显式使用left join/left outer join的情况会比较少。inner join要求右边的表达式必须返回Entities。

// 返回所有地址为2000的Order纪录,Order中必须有OrderItem

final Query query = ( "select o from Order o inner join where order by ");

left/left out/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能。在默认查询中,Entity中的集合属性默认不会被关联,集合属性默认是缓加载( lazy-load )。

// 默认JPQL编译后不关联集合属性变量(orderItems)对应的表

final Query query = ( "select o from Order o inner join where order by ");

final List result = ();

// 这时获得Order实体中orderItems( 集合属性变量 )为空

final Order order = (Order)( 0 )

// 当应用需要时,EJB3 Runtime才会执行一条SQL语句来加载属于当前Order的OrderItems

Collection orderItems = ();

这样的查询性能上有不足的地方。为了查询N个Order,我们需要一条SQL语句获得所有的Order的原始/对象属性,但需要另外N条语句获得每个Order的orderItems集合属性。为了避免N+1的性能问题,我们可以利用join fetch一次过用一条SQL语句把Order的所有信息查询出来。

// 返回所有地址为2000的Order纪录,Order中必须有OrderItem

final Query query = ( "select o from Order o inner join fetch where order by ");

由于使用了fetch,这个查询只会产生一条SQL语句,比原来需要N+1条SQL语句在性能上有了极大的提升。

比较Entity

在查询中使用参数查询时,参数类型除了String, 原始数据类型( int, double 等)和它们的对象类型( Integer, Double等),也可以是Entity的实例。

final Query query = ( "select o from Order o where = 1 order by ");

final Address address = new Address( 2001, "foo street", "foo city", "foo province" );

// 直接把address对象作为参数。

( 1, address );

批量更新(Batch Update)

JPQL支持批量更新。

Query query = ("update Order as o set =:newvender, ='fooPart' where = 'foo'");

("newvender", "barVender");

// update的记录数

int result = ();

批量删除(Batch Remove)

JPQL支持批量删除。

Query query = ("DELETE FROM Order");

int result = ();

Query query = ("DELETE FROM Order AS o WHERE ='redsoft'");

int result = ();

如果大家有更好的文档,希望大家多多分享,多多补充,共同学习,共同进步。

相关主题
文本预览
相关文档 最新文档