1.JPA概述 JPA(Java Persistence API)作为Java EE 5.0平台 JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中,图 1很好地描述了JPA的
Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE JPA由EJB 3.0软件 JPA的总体思想和现有Hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术: ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中; JPA 的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。 查询 2.实体对象 访问数据库前,我们总是要设计在应用层承载数据的领域对象(Domain Object),ORM框架将它们持久化到数据库表中。为了方便后面的讲解,我们用论坛应用为例,建立以下的领域对象: Topic是论坛的主题,而PollTopic是调查性质的论坛主题,它扩展于Topic,一个调查主题拥有多个选项PollOption。这三个领域对象很好地展现了领域对象之间继承和关联这两大核心的关系。这3个领域对象将被映射到数据库的两张表中: 其中,Topic及其子类PollTopic将映射到同一张t_topic表中,并用topic_type字段区分两者。而PollOption映射到t_polloption中。 具有ORM元数据的领域对象称为实体(Entity),按JPA的规范,实体具备以下的条件: 必须使用javax.persistence.Entity注解或者在XML映射文件中有对应的 必须具有一个不带参的构造函数,类不能声明为final,方法和需要持久化的属性也不能声明为final; 如果游离状的实体对象需要以值的方式进行传递,如通Session bean的远程业务接口传递,则必须实现Serializable接口; 需要持久化的属性,其访问修饰符不能是public,它们必须通过实体类方法进行访问。 基本注解 首先,我们对Topic领域对象进行注解,使其成为一个合格的实体类: 代码清单1:Topic实体类的注解
@Entity:将领域对象标注为一个实体,表示需要保存到数据库中,默认情况下类名即为表名,通过name属性显式指定表名,如①处的name = "T_TOPIC",表示Topic保存到T_TOPIC表中; 1) IDENTITY:表自增键字段,Oracle不支持这种方式; @Column(name = "TOPIC_ID"):属性对应的表字段。我们并不需要指定表字段的类型,因为JPA会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度,以便可以自动生成DDL语句,如③处所示; 1) DATE :等于 继承关系 Topic和PollTopic是父子类,JPA 采用多种方法来支持实体继承。在父类中必须声明继承实体的映射策略,如代码清单2所示: 代码清单2:继承实体的映射策略
对于继承的实体,在javax.persistence.InheritanceType定义了3种映射策略: SINGLE_TABLE:父子类都保存到同一个表中,通过字段值进行区分。这是我们Topic实体所采用的策略,Topic和PollTopic都保存到同一张表中,通过TOPIC_TYPE字段进行区分,Topic在T_TOPIC表中对应TOPIC_TYPE=1的记录,而PollTopic对应TOPIC_TYPE=2的记录(稍后在PollTopic实体中指定);区别的字段通过@DiscriminatorColumn说明,如②所示,区分字段对应该实体的值通过@DiscriminatorValue指定,如③所示; JOINED:父子类相同的部分保存在同一个表中,不同的部分分开存放,通过表连接获取完整数据; TABLE_PER_CLASS:每一个类对应自己的表,一般不推荐采用这种方式。 关联关系 我们再继续对PollTopic进行注解,进一步了解实体继承的JPA映射定义: 代码清单3:PollTopic映射描述
在①处,通过@DiscriminatorValue将区分字段TOPIC_TYPE的值为2。由于PollTopic实体继承于Topic实体,其它的元数据信息直接从Topic获得。 JPA规范规定任何属性都默认映射到表中,所以虽然我们没有给③处的multiple属性提供注解信息,但JPA将按照默认的规则对该字段进行映射:字段名和属性名相同,类型相同。如果我们不希望将某个属性持久化到数据表中,则可以通过@Transient注解显式指定: @Transient private boolean tempProp1; 在④处,我们通过@OneToMany指定了一个一对多的关联关系,一个PollTopic包括多个PollOption对象(我们将在稍后的PollOption中通过ManyToOne描述PollOption和PollTopic的关系,以建立PollTopic和PollOption的双向关联关系)。 下面,我们来看一下Many方PollOption实体类的映射描述: 代码清单4:PollOption映射描述
在①处通过@ManyToOne描述了PollOption和PollTopic的多对一关联关系,并通过@JoinColumn指定关联PollTopic实体所对应表的“外键”,如②所示。 当然也可以通过@OneToOne和@ManyToMany指定一对一和多以多的关系,方法差不多,不再赘述。 Lob字段 在JPA中Lob类型类型的持久化很简单,仅需要通过特殊的Lob注解就可以达到目的。下面,我们对Post中的Lob属性类型进行标注: 代码清单5 Post:标注Lob类型属性
postText属性对应T_POST表的POST_TEXT字段,该字段的类型是LONTTEXT,并且非空。JPA通过@Lob将属性标注为Lob类型,如①-1和②-1所示。通过@Basic指定Lob类型数据的获取策略,FetchType.EAGER表示非延迟加载,而FetchType. LAZY表示延迟加载,如①-2和②-2所示。通过@Column的columnDefinition属性指定数据表对应的Lob字段类型,如①-3和②-3所示。 关于JPA注解的更多信息,你可以通过这篇文章进行更加深入的学习:http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html 除了使用注解提供元数据信息外,JPA也允许我们通过XML提供元数据信息。条条道路通罗马,路路都是安康道,开发者安全可以根据自己的习惯喜好择一而从。按照JPA的规范,如果你提供了XML元数据描述信息,它将覆盖实体类中的注解元数据信息。XML元数据信息以orm.xml命名,放置在类路径的META-INF目录下。 JPA尽量让XML和注解的元数据在描述的结构上相近,降低学习曲线和转换难度,所以我们在学习注解元数据后,学习XML元数据变得非常简单。下面,我们给出以上实体的XML描述版本,你可以对照注解的描述进行比较学习: 代码清单6 XML元数据配置:orm.xml
EntityManager的创建过程 javax.persistence.spi.PersistenceProvider接口由JPA的实现者提供,该接口由启动者调用,以便创建一个EntityManagerFactory实例。它定义了创建一个EntityManagerFactory实例的方法: EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) javax.persistence.spi.PersistenceUnitInfo入参提供了创建实体 PersistenceUnitInfo接口拥有了一个void addTransformer(ClassTransformer transformer)方法,通过该方式可以添加一个javax.persistence.spi.ClassTransformer,并通过PersistenceProvider开放给容器,以便容器在实体类文件加载到JVM之前进行代码的增强,使元 图4描述了创建EntityManager的过程: 实体的状态 实体%A |
|
来自: fondofbeyond > 《我的图书馆》