前些天,我负责调研了JPA,持久化,主要是结合EJB3.0;这个项目还用了JIDE、TWaver ;相对jpa来讲,这个如果你之前做过Hibernate项目,你将会很容易理解JPA的应用。调研内容如下:
4. JPA 1.0
4.1 ORM: 单表,1:1, 1:n, n:m
4.2 其他: PK生成策略,延迟加载策略,级联(cascading)选项
4.3 JPQL: 单表查询,多表结合查询
1. 概述
Java Persistence API作为JavaEE5.0平台的标准的ORM规范,将得到所有JavaEE所有服务器的支持。
JPA由EJB3.0软件开发组专家开发,作为JSR-220的实现的一部分。
目前hibernate、Toplink以及OpenJPA都提供了JPA的支持。
JPA包括三个方面技术:
ORM映射元数据,JPA支持XML与JDK5.0注释,元数据描述对象与表之间的映射关系,框架可以将实体对象持久化到数据库当中。
JPA持久化API,用来操作实体对象,执行curd操作,框架在后台替我们完成了所有的事情,开发者可以从JDBC和SQL代码中解脱出来。
查询语言,这是持久化操作很重要的一个概念。通过面向对象而非面向数据库的查询数据,避免程序与SQL的紧密耦合。
2. 实体对象
访问数据库之前,我们总是要设计在应用层承载数据的领域对象,ORM将它们持久化到数据库当中。
按照JPA规范实体必须具备以下要求:
必须使用javax.persistence.Entity注解或者使用XML映射文件中相对应的元素。
必须具备一个不带参数的构造函数,类不能声明成final,方法和持久化的属性也不能声明成final,并且被持久化的属性访问修饰符不能为public。
如果游离状的实体需要以值的方式进行传递,如EJB的Session bean,则必须实现Serializable接口。
3. 基本注解
@Entity:将领域模型标注为一个实体,默认情况下类为表名,可以通过name属性重新指定。
@Id:属性对应表的主键。
@Column:属性对应表的字段。
@GenaratedValue:主键生成策略,通过startage属性指定。在4.0会解释主键生成策略。
4. 主键生成策略
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface GeneratedValue {
GenerationType strategy() default AUTO;
String generator() default "";
}
IDENTITY:主键由数据库自动生成。
AUTO:JPA自动选择合适的主键生成策略,默认选线。
SEQUENCE:通过序列产生主键,条件是数据库必须支持序列。
TABLE:通过表产生主键,使用该策略更易于数据库的移值。
5. 实体关系
实体之间的关系有一对一,一对多,多对一,多多对。关系是多态的。
多对一
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
}
一对一
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
String mappedBy() default "";
}
6. 双向关联特性
双向关系的的反向端必须通过OnToOne,OnToMany或者ManyToMany注解的MappedBy元素必须指向它的持久端。MappendBy表述主控端的属性或字段。
一对多,多对一双向关系中的多端必须是持久端,因此不能再ManyToOne中使用MappedBy属性。
对于一对一双向关联关系,包括对应的外键(foreign key)那一段时持久化。
对于多对多双向关联关系都是持久端。
7. 延迟加载
FetchType.EAGER:代表立即加载。
FetchType.LAYZ:代表延迟加载策略。
8. 多级级联
REFRESH指定当你在访问期间,如果数据库数据发生改变时,你的数据是否更 新。
PERSIST指定在保存1数据的时是否会同时保存级联的n数据。
MERGE指定当1处于游离状态被修改了,n的数据也会被修改。
REMOVE指定在删除1的同时是否删除与之级联的n数据。
ALL指定包含所有的级联的N方。
9. Java Persistence Query language
基于首次在EJB2.0引用的EJB查询语言,java持久化查询语言是一种可移植的查询语言。旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起.使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL.
10JPA2.0与JPA1.0
JPA2.0也跟Hibernate一样,也分为一级缓存,二级缓存,而JPA1.0不支持二级缓存,二级缓存是跨事物场景的。当二级缓存有效时,你就不能通过事物来保护并发数据,而只能依靠锁的策略。
11 事物与EntityManager
EntityManager对象事物管理分为二种,由JTA和RESOURCE_LOCAL来控制。
JTA EntityManager一般在容器里面使用,而RESOURCE_LOCAL(应用托管的EntityManager)数据库本地化事物,一般在J2SE环境下使用。
通过容器来传递PersistenceContext而不是通过程序来自己传递EntityManager,它的生命周期由容器进行管理。
在J2SE环境下,RESOURCE_LOCAL由程序来创建EntityManagerFactory,并由EntityManagerFactory来创建EntityManger,这种方式就是RESOURCE_LOCAL的基本使用方式。
12 监听实体调用
监听实体主要有PostLoad , PostPersist , PostRemove , PostUpdate, pre-persist , pre-remove 等。调用如下:
public class UserListeners {
@PostRemove
public void dothing(User user) {
System.out.println("加载..........." + user.getUserName());
}
} @Entity
@org.hibernate.annotations.Entity(dynamicInsert = true)
@EntityListeners(UserListeners.class)
public class User implements Serializable{
………………..
}
13 乐观锁定
乐观锁定它可以确保在实体的状态从数据库读取出来,在没有中间插入的其它事物更改了与这个实体对应数据库记录的情况下,才把更新后实体的状态更新到数据库。它确保对数据的更新和删除与数据库的当前状态保持一致,并且不会丢失中间的修改。如果应用程序想启用实体的乐观锁,就必须为实体指定version属性。如果没有将乐观锁作为实体状态的一部分进行定义,应用程序就要自己去维护数据的完整性。
直接映射
实体的生命周期
EntityManager用于管理实体实例的生命周期,一个实体实例可以分为new,managed,detached,或remove
一个新创立的实体实例没有持久化标识,并且还没有跟持久化上下相关联。
一个受管的实体实例有一个正与持久化上下文相关联的持久化标识。
一个脱管的实体实例有持久化标识,但是这个标识没有跟持久化上下文相关联。
被删除的实体实例有持久化标示,并且与持久化上下文相关联,但是已经计划从数据库中删除。
@Enumerated
@Temporal
@Lob
@Transient
关系映射
@OneToOne
@ManyToOne
@OneToMany
@ManyToMany
@MapKey
@OrderBy
继承
@DiscriminatorColumn
@DiscriminatorValue
@MappedSuperclass
@AssociationOverride
@AssociationOverrides
@AttributeOverride
@AttributeOverrides
锁定
@PostPersist
@PreRemove
@PostRemove
@PreUpdate
@PostUpdate
@PostLoad
@EntityListeners
@ExcludeDefaultListeners
@ExcludeSuperclassListeners
查询
@NamedQueries
@NamedNativeQuery
@NamedNativeQueries
@QueryHint
@ColumnResult
@EntityResult
@FieldResult
@SqlResultSetMapping
@SqlResultSetMappings
综合上面调研的内容,上传一个基本(简单)的例子。该例子主要描述了JPA双向一对一,双向一对多,双向多对多,单向一对一,单向一对多,单向多对一与单向多对多,测试代码中使用了级联、延迟加载策略,单表查询、多表查询JPQL。JPA版本采用Hibernate3.2