一篇 JPA 总结
概述
下面是 JDBC 在 Java 应用和数据库之间的位置,充当着一个中间者,供 Java 应用程序访问所有类别的数据库,建立一个标准
JPA 如同 JDBC 一样,为 Java 应用程序使用 ORM 框架建立一个标准
- JPA 和 Hibernate 的关系
- JPA 是规范:JPA 本质上是一种 ORM 规范,不是 ORM 框架,只是定制了一些规范,提供了一些编程的 API 接口,具体实现由 ORM 厂商实现
Hibernate 是实现:Hibernate 除了是一种 ORM 框架之外,他也是一种 JPA 实现
HelloWorld
- 步骤
- 创建 presitence.xml,在这个文件中配置持久化单元
- 指定跟哪个数据库进行交互
- 指定使用哪个持久化框架以及配置该框架的基本属性
- 创建实体类,使用 annotation 来描述实体类跟数据库表之间的映射关系
- 使用 JPA API 完成数据的增、删、改、查操作
- 创建 EntityManagerFactory(对应于 Hibernate 中的 SessionFactory)
- 创建 EntityManager(对应 Hibernate 中的 Session)
- 创建 presitence.xml,在这个文件中配置持久化单元
导入 jar 包
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.21</version></dependency>
- persistence.xml
JPA 规范要求在类路径的 META-INF 目录下防止 persistencce.xml,文件的名称是固定的
<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"><persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"><!--配置使用什么 ORM 产品--><!--若 JPA 项目中只有一个 JPA 产品的实现,则可以不配置该节点--><provider>org.hibernate.jpa.HibernatePersistenceProvider</provider><class>com.jpa.first.both.many2many.Item</class><properties><!--配置数据库连接--><property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/jpa"/><property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/><property name="hibernate.connection.username" value="root"/><property name="hibernate.connection.password" value="zy961029"/><!--配置 hibernate 的基本属性--><property name="hibernate.hbm2ddl.auto" value="update"/><property name="hibernate.show_sql" value="true"/><property name="hibernate.format_sql" value="true"/></properties></persistence-unit></persistence>
注解
- @Entity
- @Entity 标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。
- @Table
- 当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用
- @id
- @Id 标注用于声明一个实体类的属性映射为数据库的主键列
- @Id标注也可置于属性的getter方法之前
- @GeneratedValue
- @GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment
- IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式
- AUTO: JPA自动选择合适的策略,是默认选项
- TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
- SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
- @GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment
- @Basic
- 表示一个简单的属性到数据表的字段的映射,对于没有任何标注的 getXxx() 方法,默认为 @Basic
- fetch 表示属性的读取策略,有 EAGER 和 LAZY 两种,分别为主支抓取和延迟加载
- optional 表示该属性是否允许为 null,默认为 true
- 表示一个简单的属性到数据表的字段的映射,对于没有任何标注的 getXxx() 方法,默认为 @Basic
- @Column
- 当实体的属性与其映射的数据库表的列不同名时需要使用 @Column 标注说明,还有属性 unique、nullable、length 等
- @Transient
- 表示该属性并非一个到数据库表的字段的映射,ORM 框架将忽略该属性
- 如果一个属性并非数据库表的字段映射,就务必将其标识为 @Transient,否则ORM 框架默认为其注解 @Basic,例如工具方法不需要映射
- @Temporal
- 在 JavaAPI 中没有定义 Date 类型的精度,而在数据库中表示 Date 类型的数据类型有 Date,Time,TimeStamp 三种精度(日期,时间,两者兼具),进行属性映射的时候可以使用 @Temporal 注解调整精度
JPA API
- EntityManagerFactory
- EntityManagerFactory 用来创建 EntityManager 实例
- 使用 Persistence 类获取 EntityManagerFactory 实例,该类包含一个名为 createEntityManagerFactory 的静态方法
- createEntityManager 有两个重载方法,如下:
- 第二个重载方法和上述的方法唯一不同的是不需要传入第二个参数
- isOpen(),检查 EntityManagerFactory 是否处于打开状态
- close(),关闭 EntityManagerFactory,EntityManagerFactory 关闭后将释放所有资源,isOpen() 方法将返回 false
- EntityManager
代码
public void testJpa() {// 创建 EntityManagerFactoryString persistenceUnitName = "persistenceUnit";EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);// 创建 EntityManagerEntityManager entityManager = entityManagerFactory.createEntityManager();// 获取事务对象并开启事务EntityTransaction entityTransaction = entityManager.getTransaction();entityTransaction.begin();// 进行持久化操作 entityManager.xxx();// 提交事务entityTransaction.commit();// 关闭 EntityManagerentityManager.close();// 关闭 EntityManagerFactoryentityManagerFactory.close();}
- 常用方法测试
我们在上述代码持久化部分测试以下方法,将初始化部分代码放入 @Before 内,将提交事务部分代码放入 @After 内,持久化操作方法在 @Test 内执行
public class EntityManagerMethodTest {private EntityManagerFactory entityManagerFactory;private EntityManager entityManager;private EntityTransaction entityTransaction;@Beforepublic void init() {entityManagerFactory = Persistence.createEntityManagerFactory("persistenceUnit");entityManager = entityManagerFactory.createEntityManager();entityTransaction = entityManager.getTransaction();entityTransaction.begin();}@Afterpublic void destroy() {entityTransaction.commit();entityManager.close();entityManagerFactory.close();}@Testpublic void test() {// 持久化操作}}
- find():类似于 Hibernate 中 Session 的 get 方法
- getReference():类似于 Hibernate 中 Session 的 load 方法,即在需要的时候才会去执行 SQL 语句,初始化对象,否则返回的为代理对象
- persistence():类似于 Hibernate 中 Session 的 save 方法,但此方法所要存取的对象若有 id,那么会抛异常
- remove():类似于 Hibernate 中 Session 的 delete 方法,但此方法只可删除持久化对象,而 hibernate 的方法可以删除游离对象(不在缓存中,但在数据库中可能有对象,该对象有 id;缓存是指利用方法从数据库中获取到对象且将其初始化了,那么关闭 entityManager、提交事务后该对象依旧可使用)
关联关系映射(使用 IDEA 可以使用实体生成表,也可以使用对应的额表逆向生成实体类)
- 单向多对一(orders - customer)
- 表结构(oreders 表中有 customer 表的外键映射 cus_id)
- 实体映射
-
@ToString@Entity@Table(name = "customer", schema = "jpa")public class CustomerEntity {private int id;private String cusName;@Id@Column(name = "id", nullable = false)@GeneratedValue(strategy = GenerationType.AUTO)public int getId() {return id;}public void setId(int id) {this.id = id;}@Basic@Column(name = "cus_name", nullable = true, length = 20)public String getCusName() {return cusName;}public void setCusName(String cusName) {this.cusName = cusName;}}
-
- IDEA 逆向生成实体(记得添加主键生成策略)
- 多对一映射方法测试
添加数据
/*** n-1 将数据插入表中,建议先插入一的一端*/@Testpublic void testMany2OnePersistence() {CustomerEntity customerEntity = new CustomerEntity();customerEntity.setCusName("bgZyy");OrdersEntity orderEntity1 = new OrdersEntity();orderEntity1.setOrderNaem("CC-a-AA");OrdersEntity orderEntity2 = new OrdersEntity();orderEntity2.setOrderNaem("DD-b-BB");orderEntity1.setCustomerByCusId(customerEntity);orderEntity2.setCustomerByCusId(customerEntity);entityManager.persist(customerEntity);entityManager.persist(orderEntity1);entityManager.persist(orderEntity2);}
- 获取数据
- 表结构(oreders 表中有 customer 表的外键映射 cus_id)
- 单向一对多(company - employee)
- 表结构
- 实体映射
- 关联关系维护
- 一对多方法测试
添加数据
@Testpublic void testOne2ManyPersistence() {CompanyEntity companyEntity = new CompanyEntity();companyEntity.setComName("IT");EmployeeEntity employeesEntity = new EmployeeEntity();employeesEntity.setEmpName("gg");EmployeeEntity employeesEntity1 = new EmployeeEntity();employeesEntity1.setEmpName("yy");// 员工集合Collection<EmployeeEntity> employeeEntities = new ArrayList<>();employeeEntities.add(employeesEntity);employeeEntities.add(employeesEntity1);// 为 company 添加员工的集合信息companyEntity.setEmployeesById(employeeEntities);// 执行保存操作entityManager.persist(employeesEntity);entityManager.persist(employeesEntity1);entityManager.persist(companyEntity);}
获取数据
@Testpublic void testOne2ManyFind() {CompanyEntity companyEntity;companyEntity = entityManager.find(CompanyEntity.class, 1);System.out.println(companyEntity.getComName());System.out.println(companyEntity.getEmployeesById().size());}
- 表结构
- 双向一对一映射
- 表结构
- 实体映射
- 方法测试
- 保存数据(先保存不维护关联关系的一端,否则会多出 UPDATE 语句)
- 保存数据(先保存不维护关联关系的一端,否则会多出 UPDATE 语句)
- 使用 IDEA 反向生成实体(双向一对一)
- 表结构
- 双向多对多映射
- 配置一览图(实体生成数据表),核心配置如下图所示,对于添加数据获取数据代码不再展示
- 配置一览图(实体生成数据表),核心配置如下图所示,对于添加数据获取数据代码不再展示
JPQL(Java Persistence Query Language)
- JPQL 语言可以是 select、update、delete 语句,他们都是通过 Query 接口封装执行的。
- Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。
- 方法测试
- 获取某一范围所有属性的集合
- 获取某一范围部分属性的集合,其和获取所有属性的集合所使用的方法一样,不同的是 jpql 语句不一样,且需要对应的实体有部分属性的构造器
- 使用本地 SQL 语句查询,和以上两个所使用的方法不一样,此时使用 createNativeQuery()
- 获取某一范围所有属性的集合
JPQL 还支持二级缓存,order by 子句,group by 子句,聚合查询,having 子句,关联查询,子查询等,JPQL 还有大量函数,如字符串处理函数,算术函数和日期函数等功能,这里就不再一一列举,下面列出常用的方法和函数(了解即可):
- 常用函数
- concat(String s1, String s2):字符串合并/连接函数。
- substring(String s, int start, int length):取字串函数。
- trim([leading|trailing|both,] [char c,] String s):从字符串中去掉首/尾指定的字符或空格。
- lower(String s):将字符串转换成小写形式。
- upper(String s):将字符串转换成大写形式。
- length(String s):求字符串的长度。
- Query 接口主要方法
- int executeUpdate(),用于执行update或delete语句。
- List getResultList(),用于执行select语句并返回结果集实体列表。
- Object getSingleResult(),用于执行只返回单个结果实体的select语句
- Query setFirstResult(int startPosition),用于设置从哪个实体记录开始返回查询结果。
- Query setMaxResults(int maxResult),用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询。
Spring 整合 JPA
- 整合什么
- Spring 管理 EntityManager,JPA 使用声明式事务
- 使用什么整合
- LocalContainerEntityManagerFactoryBean,其适用于所有环境
- 整合步骤
- jar 包
- Spring + Hibernate + JPA + C3P0 + MySQL
- 创建 Spring 配置文件
- 配置数据源
- 配置 EntityManagerFactoryBean,即 LocalContainerEntityManagerFactoryBean,其需要属性 DataSource、jpaVendorAdapter(JPA 提供商的适配器,通过内部 bean 的方式)、packagesToScan(Entity 在哪个包下),配置 JPA 基本属性(show_sql 等)
- 配置 JPA 使用的事务管理器(JPAtransactionManager)
- 配置事务
- 在 DAO 中使用 EntityManager
- 如何获取到和当前事务关联的 EntityManager 对象?
- 通过 @PesistenceContext 注解标记成员变量
- 一览图
- jar 包
以上就是我所学到有关 JPA 的知识,还望有用!再就是希望大牛们可以提点建设性的建议,共同进步,先谢谢了!
转载于:https://www.cnblogs.com/bgzyy/p/9173615.html
一篇 JPA 总结相关推荐
- 第三篇 SpringBoot 2 x中使用JPA
上一篇使用了JdbcTemplate去访问数据库,毕竟使用的是原生的SQL形式,像我这种懒人是肯定不会考虑的了.. 这次记录下使用JPA来极大的减少我们的代码量 首先,还是准备好SQL文件 DROP ...
- 【SpringBoot框架篇】11.Spring Data Jpa实战
文章目录 1.简介 1.1.JPA 1.2.Spring Data Jpa 1.3.Hibernate 1.4.Jpa.Spring Data Jpa.Hibernate三者之间的关系 2.引入依赖 ...
- Java9中使用jpa_第三篇:SpringBoot中使用JPA
上一篇使用了JdbcTemplate去访问数据库,毕竟使用的是原生的SQL形式,像我这种懒人是肯定不会考虑的了.. 这次记录下使用JPA来极大的减少我们的代码量 首先,还是准备好SQL文件 DROP ...
- SpringBoot学习之旅(七)---JPA进阶篇之自定义查询、修改、分页
文章目录 前言 源码下载 其他文章 查询关键字 自定义Select和Update 分页及自定义分页 自定义分页 分页查询的业务代码 前言 前一节SpringBoot学习之旅(六)-JPA操作MySql ...
- Spring Boot第四篇:SpringBoot 整合JPA
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA 的目标之一是制定一个可以由很多供应商 ...
- jpa多表关联查询_JPA【关联查询篇】
摘要:本文主要介绍JPA的多表关联查询(一对一.一对多.双向关联.多对一.多对多)以及N+1查询的优化. 1. JPA多表关联查询 多表关联查询就是实现使用一个实体类对象操作或者查询多个表的数据. 配 ...
- 最新SpringBoot2.0X整合SpringData JPA实战完整篇
先来张效果图吧 一.pom.xml 导入依赖包 <dependencies><dependency><groupId>org.springframework.boo ...
- Spring Boot 2.x 多数据源配置之 JPA 篇
场景假设:现有电商业务,商品和库存分别放在不同的库 配置数据库连接 app:datasource:first:driver-class-name: com.mysql.cj.jdbc.Driverur ...
- 图文详解SpringBoot JPA反向工程【逆向工程篇】
本文介绍在IDEA中如何通过逆向工程生成数据库表对应的实体类(entity). JPA逆向工程是什么 所谓的逆向工程就是通过数据库的结构生成代码,只要是持久层框架基本都提供逆向工程支持. 为什么需要逆 ...
- 一篇总结的很好的Spring data jpa 文章,里面包含多种查询方式,可以结合api使用
http://www.cnblogs.com/ityouknow/p/5891443.html
最新文章
- 云数据中心异构资源管理大有可为
- Redis4.0 Cluster — Centos7
- lambda java_Java Lambdas简介
- C语言 函数指针和指针函数区别 - C语言零基础入门教程
- JS事件 卸载事件 当用户退出页面时(页面关闭、页面刷新等),触发onUnload事件,同时执行被调用的程序。注意:不同浏览器对onunload事件支持不同。...
- 用英语描述计算机操作,操作系统的英文介绍
- 服务器安装rabbitmq教程
- 开发者必备Linux命令
- mysql5.7安装
- 一位19年的Mac用户:“我真的很讨厌库克”
- 泰勒公式的展开细节解析、本质、联想与思考
- CF1041F Ray in the tube
- C++连接MYSQL教程
- 一文读懂中国5G的真正实力
- 【项目实例】使用C#开发纽曼USB来电通来电弹屏客户端小结
- [poj 1741]Tree 点分治
- Visio中添加《include》包含符号
- Python异步并发机制详解,让你的代码运行效率就像搭上了火箭!!!
- 离散数学·集合论【基本的集合恒等式】
- 【历史上的今天】7 月 25 日:IBM 获得了第一项专利;Verizon 收购雅虎;亚马逊发布 Fire Phone
热门文章
- linux asp.net 性能优化,ASP.NET性能优化之减少请求
- Ubuntu如何修改用户密码
- thinkphp去重,distinct、group
- python 递归目录和文件 修改主组_python下递归遍历目录和文件的方法介绍
- 清新脱俗的Java选课系统
- (转载)o(1), o(n), o(logn), o(nlogn) 时间复杂度
- Chrome、Firefox 浏览器常用设置及操作
- Navicat Premium 15 逆向表到模型
- 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_23-CMS前端页面查询开发-分页查询实现...
- 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_6_Stream流中的常用方法_count...