JPA定义了Java ORM及实体操作API的标准。本文摘录了JPA的一些关键信息以备查阅。

如果有hibernate的基础,通过本文也可以快速掌握JPA的基本概念及使用。

1 JPA概述

JPA(Java Persistence API,Java持久化API),定义了对象-关系映射(ORM)以及实体对象持久化的标准接口。

JPA是JSR-220(EJB3.0)规范的一部分,在JSR-220中规定实体对象(EntityBean)由JPA进行支持。

所以JPA不局限于EJB3.0,而是作为POJO持久化的标准规范,可以脱离容器独立运行,开发和测试更加方便。

JPA在应用中的位置如下图所示:

JPA维护一个Persistence Context(持久化上下文),在持久化上下文中维护实体的生命周期。主要包含三个方面的内容:

  1. ORM元数据。JPA支持annotion或xml两种形式描述对象-关系映射。
  2. 实体操作API。实现对实体对象的CRUD操作。
  3. 查询语言。约定了面向对象的查询语言JPQL(Java Persistence Query Language)。

JPA的主要API都定义在javax.persistence包中。如果你熟悉Hibernate,可以很容易做出对应:

org.hibernate javax.persistence 说明
cfg.Configuration Persistence 读取配置信息
SessionFactory EntityManagerFactory 用于创建会话/实体管理器的工厂类
Session EntityManager 提供实体操作API,管理事务,创建查询
Transaction EntityTransaction 管理事务
Query Query 执行查询

2 实体生命周期

实体生命周期是JPA中非常重要的概念,描述了实体对象从创建到受控、从删除到游离的状态变换。对实体的操作主要就是改变实体的状态。

JPA中实体的生命周期如下图:

  1. New,新创建的实体对象,没有主键(identity)值
  2. Managed,对象处于Persistence Context(持久化上下文)中,被EntityManager管理
  3. Detached,对象已经游离到Persistence Context之外,进入Application Domain
  4. Removed, 实体对象被删除

EntityManager提供一系列的方法管理实体对象的生命周期,包括:

  1. persist, 将新创建的或已删除的实体转变为Managed状态,数据存入数据库。
  2. remove,删除受控实体
  3. merge,将游离实体转变为Managed状态,数据存入数据库。

如果使用了事务管理,则事务的commit/rollback也会改变实体的状态。

3 实体关系映射(ORM)

3.1 基本映射

对象端 数据库端 annotion 可选annotion
Class Table @Entity @Table(name="tablename")
property column @Column(name = "columnname")
property primary key @Id @GeneratedValue 详见ID生成策略
property NONE @Transient  

3.2 ID生成策略

ID对应数据库表的主键,是保证唯一性的重要属性。JPA提供了以下几种ID生成策略

  1. GeneratorType.AUTO ,由JPA自动生成
  2. GenerationType.IDENTITY,使用数据库的自增长字段,需要数据库的支持(如SQL Server、MySQL、DB2、Derby等)
  3. GenerationType.SEQUENCE,使用数据库的序列号,需要数据库的支持(如Oracle)
  4. GenerationType.TABLE,使用指定的数据库表记录ID的增长 需要定义一个TableGenerator,在@GeneratedValue中引用。例如:

    @TableGenerator( name="myGenerator", table="GENERATORTABLE", pkColumnName = "ENTITYNAME", pkColumnValue="MyEntity", valueColumnName = "PKVALUE", allocationSize=1 )

    @GeneratedValue(strategy = GenerationType.TABLE,generator="myGenerator")

3.3 关联关系

JPA定义了one-to-one、one-to-many、many-to-one、many-to-many 4种关系。

对于数据库来说,通常在一个表中记录对另一个表的外键关联;对应到实体对象,持有关联数据的一方称为owning-side,另一方称为inverse-side。

为了编程的方便,我们经常会希望在inverse-side也能引用到owning-side的对象,此时就构建了双向关联关系。 在双向关联中,需要在inverse-side定义mappedBy属性,以指明在owning-side是哪一个属性持有的关联数据。

对关联关系映射的要点如下:

关系类型 Owning-Side Inverse-Side
one-to-one @OneToOne @OneToOne(mappedBy="othersideName")
one-to-many / many-to-one @ManyToOne @OneToMany(mappedBy="xxx")
many-to-many @ManyToMany @ManyToMany(mappedBy ="xxx")

其中 many-to-many关系的owning-side可以使用@JoinTable声明自定义关联表,比如Book和Author之间的关联表:

@JoinTable(name = "BOOKAUTHOR", joinColumns = { @JoinColumn(name = "BOOKID", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "AUTHORID", referencedColumnName = "id") })

关联关系还可以定制延迟加载和级联操作的行为(owning-side和inverse-side可以分别设置):

通过设置fetch=FetchType.LAZY 或 fetch=FetchType.EAGER来决定关联对象是延迟加载或立即加载。

通过设置cascade={options}可以设置级联操作的行为,其中options可以是以下组合:

  • CascadeType.MERGE 级联更新
  • CascadeType.PERSIST 级联保存
  • CascadeType.REFRESH 级联刷新
  • CascadeType.REMOVE 级联删除
  • CascadeType.ALL 级联上述4种操作

3.4 继承关系

JPA通过在父类增加@Inheritance(strategy=InheritanceType.xxx)来声明继承关系。A支持3种继承策略:

  1. 单表继承(InheritanceType.SINGLETABLE),所有继承树上的类共用一张表,在父类指定(@DiscriminatorColumn)声明并在每个类指定@DiscriminatorValue来区分类型。
  2. 类表继承(InheritanceType.JOINED),父子类共同的部分公用一张表,其余部分保存到各自的表,通过join进行关联。
  3. 具体表继承(InheritanceType.TABLEPERCLASS),每个具体类映射到自己的表。

其中1和2能够支持多态,但是1需要允许字段为NULL,2需要多个JOIN关系;3最适合关系数据库,对多态支持不好。具体应用时根据需要取舍。

4 事件及监听

通过在实体的方法上标注@PrePersist,@PostPersist等声明即可在事件发生时触发这些方法。

5 Query Language 查询语言

JPA提供两种查询方式,一种是根据主键查询,使用EntityManager的find方法:

T find(Class entityClass, Object primaryKey)

另一种就是使用JPQL查询语言。JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernate HQL很相似。

使用EntityManager的createQuery方法:

Query createQuery(String qlString)

5.1 使用参数

可以在JPQL语句中使用参数。JPQL支持命名参数和位置参数两种参数,但是在一条JPQL语句中所有的参数只能使用同一种类型。

举例如下:

  • 命令参数

Query query = em.createQuery("select p from Person p where p.personid=:Id"); query.setParameter("Id",new Integer(1));

  • 位置参数

Query query = em.createQuery("select p from Person p where p.personid=?1"); query.setParameter(1,new Integer(1));

5.2 命名查询

如果某个JPQL语句需要在多个地方使用,还可以使用@NamedQuery 或者 @NamedQueries在实体对象上预定义命名查询。

在需要调用的地方只要引用该查询的名字即可。

例如:

@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1")

@NamedQueries({ @NamedQuery(name="getPerson1", query= "FROM Person WHERE personid=?1"), @NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1") })

Query query = em.createNamedQuery("getPerson");

5.3 排序

JPQL也支持排序,类似于SQL中的语法。例如: Query query = em.createQuery("select p from Person p order by p.age, p.birthday desc");

5.4 聚合查询

JPQL支持AVG、SUM、COUNT、MAX、MIN五个聚合函数。例如:

Query query = em.createQuery("select max(p.age) from Person p"); Object result = query.getSingleResult(); String maxAge = result.toString();

5.5 更新和删除

JPQL不仅用于查询,还可以用于批量更新和删除。

如:

Query query = em.createQuery("update Order as o set o.amount=o.amount+10"); //update 的记录数 int result = query.executeUpdate();

Query query = em.createQuery("delete from OrderItem item where item.order in(from Order as o where o.amount<100)"); query.executeUpdate();

query = em.createQuery("delete from Order as o where o.amount<100"); query.executeUpdate();//delete的记录数

5.6 更多

与SQL类似,JPQL还涉及到更多的语法,可以参考:http://docs.oracle.com/cd/E11035_01/kodo41/full/html/ejb3_langref.html

6 事务管理

JPA支持本地事务管理(RESOURCELOCAL)和容器事务管理(JTA),容器事务管理只能用在EJB/Web容器环境中。

事务管理的类型可以在persistence.xml文件中的“transaction-type”元素配置。

JPA中通过EntityManager的getTransaction()方法获取事务的实例(EntityTransaction),之后可以调用事务的begin()、commit()、rollback()方法。

Date: 2012-12-30 16:46:29 CST

Author: Holbrook

Org version 7.8.11 with Emacs version 24

Validate XHTML 1.0

JPA教程:JPA概述、JPA实体生命周期、JPA实体映射关系、JPA查询语言相关推荐

  1. Java持久性API(JPA)第7讲——实体生命周期及生命周期回调方法

    源贴地址:http://blog.csdn.net/javaeeteacher/archive/2007/06/25/1665345.aspx 目标与主要内容: u        掌握实体的生命周期: ...

  2. 使用 Apache OpenJPA 开发 EJB 3.0 应用,第 6 部分: 处理实体生命周期事件的回调

    企业应用开发过程中,经常会存在这样的需求:当企业应用中的某些数据被增加.删除.修改时,引发一些特定的动作,完成企业应用中的一些特别的要求,比如企业应用中要完成数据操作日志.处理数据之间的某种关系.或者 ...

  3. mybatisPlus 实体类与数据库表映射关系

    使用mybatisPlus时,会确定实体类和数据的映射关系 具体的映射方法有两种: 1.默认:采用驼峰映射规则,例如MyUserTable 对应的数据库表为 my_user_table ;  TEMy ...

  4. Vue.js 系列教程 3:Vue-cli,生命周期钩子

    原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...

  5. 软件测试 通用技术04 缺陷基本概述 缺陷的生命周期 缺陷的识别 缺陷报告 缺陷报告模板 测试需求、测试用例、缺陷报告的关系

    1 缺陷基本概述 1.1 缺陷的定义(重要!) 软件未实现产品说明书要求的功能: 软件出现了产品说明书指明不应该出现的功能: 软件实现了产品说明书未提到的功能: 软件未实现产品说明书虽未明确提及但应该 ...

  6. 软件工程导论概述----软件的生命周期

    软件的生命周期 软件生命周期 软件生命周期 软件定义时期 软件开发时期 软件运行时期 软件生命周期 • 软件从开始计划到最后废弃不用整个阶段称为计算 机软件的生命周期. • 软件生命周期分为三个时期: ...

  7. k8s教程(pod篇)-生命周期、重启策略及健康检查

    文章目录 01 引言 02 pod生命周期 03 pod重启策略 04 pod健康检查和服务可用性检查 4.1 方式一:ExecAction 4.2 方式二:TCPSocketAction 4.3 方 ...

  8. mysql test 映射到实体_将MySql视图映射到JPA Entitites,使用哪个唯一...

    我不认为有一种标准方式,但这种方法似乎值得尝试. 想法是为视图动态生成唯一的"id"值(类似于rownum).来自Create a view with column num_row ...

  9. JPA 实体生命周期图

    图 1-1 JPA 实体生命周期回调事件批注 "图 1-1 JPA 实体生命周期回调事件批注"的描述" 转载于:https://blog.51cto.com/pz0513 ...

最新文章

  1. Visual Basic 2005 – 如何播放剪贴簿中的音效数据
  2. python测试脚本项目全程教程_《手把手教你》系列练习篇之5-python+ selenium自动化测试(详细教程)...
  3. 如何使html中的din居中,HTML+CSS--position大法好
  4. 不装oracle进行远程连接解决办法 .
  5. android studio导出apk_Android 应用构建速度提升的十个小技巧
  6. 什么是页损坏 mysql_MySQL数据库页损坏怎么办,innodb_force_recovery参数帮你解决问题...
  7. linux网络命令详解
  8. mysql 转ascii_MySQL ascll()函数
  9. 大厂爱考的 Binder 系统服务注册问题怎么破?
  10. MATLAB的语言基础知识
  11. 物业为什么要用微小区SaaS系统进行管理
  12. git实用技巧:将多次commit合并为一次
  13. 淘客外卖返利小程序搭建 - 美团联盟外卖返利小程序平台、饿了么返利小程序系统、外卖cps小程序
  14. HDU5745 La Vie en rose
  15. 中国金属包装容器制造行业竞争格局分析与投资规划深度研究报告2022-2028年版
  16. 计算机组成原理课程设计-logisim仿真补码一位乘
  17. python stdin.write_如何写入Python子进程的stdin?
  18. Sketch 插件开发指南
  19. 启动项目报错:null, message from server: “Host ‘XXX‘ is not allow
  20. Java 平衡二叉树之单旋(左旋,右旋)与双旋

热门文章

  1. Qt多线程学习:创建多线程
  2. python——正则表达式
  3. Windows下的cmd小技巧
  4. Windows下配置单机Hadoop环境
  5. (chap1 web网络基础) URI和URL
  6. C++ Primer 5th笔记(7)chapter7 类:编译相关
  7. python—类和对象之浅拷贝和深拷贝详细讲解
  8. ATF里面都有什么?
  9. Vue删除数据成功后如何刷新表格数据
  10. intellij 快捷键