Java学习笔记13——Spring Data JPA

时间:2023-02-04 16:11:08

一、Spring Data JPA概述

1.Spring Data JPA

Spring基于ORM框架、JPA规范封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作,它提供了包括增删改查等在内的常用功能,且易于扩展。

它提供了许多编程接口:

Repository:最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描的时候自动识别;

CrudRepositoryRepository的子接口,提供增删改查CRUD的功能;

PagingAndSortingRepositoryCrudRepository的子接口,添加分页排序的功能;

JpaRepositoryPagingAndSortingRepository的子接口,增加批量操作等功能;

JpaSpeccificationExecutor:用来做复杂查询的接口。

2.建立用户管理项目

1)建立工程,准备开发工具Navicat、创建表和Eclipse工程以及包结构——repository(存放自定义的数据操作接口),model(存放实体模型),service(存放服务层的接口和实现),controllerMVC项目建立,存放控制器),exception(存放异常类),test(存放测试类);

2)导入需要的jar:Spring基础jar包,Spring Data Commons jar包,Spring Data JPA jar包,Hibernate相关jar包,MySQL数据库连接包,日志相关jar包,其他jar包。

3)配置与编码:创建配置,Spring上下文applicationContext.xml和管理持久化的配置文件persistence.xml

persistence.xmlproperties标签中声明数据库连接的驱动,配置方言,激活Hibernate查询日志功能、优雅地输出SQL、添加一条解释型标注,配置如何根据java模型生成数据表结构,常用update/validate

applicationContext.xml文件:用context标签定义服务层代码存放的包的扫描路径,用bean定义实体的工厂bean、定义事务管理器,配置JPA信息4个属性,声明采用注解的方式申明事务。

编写实体类(Entity/Table/Id/GeneratedValue),接口继承JpaRepositoyUserService接口,UserService接口实现类(Autowired)、测试类、异常类。

 

二、Spring Data JPA实现增删改查

1.UserService接口中定义增删改查抽象方法,在接口实现类中用调用UserRepository的方法实现增删改查:delete删除或批量删除,findAll查找所有,findOne查找单个;save保存单个或批量保存,saveAndFlush保存并刷新到数据库。

2.JpaRepository支持接口规范方法名查询,意思是如果【在接口中定义】的查询方法符合它的【命名规则】,就可以不用写实现,如findByName这个方法表示从数据库中查询Name这个属性为XXX的所有记录。

1)查询方法名构造方法:find+全局修饰)+By+实体的属性名称+限定词+连接词+...(其他实体属性)+OrderBy+排序属性+排序方向。

其中限定词和连接词统称为“关键词”。

全局修饰:Distinct,Top,First

关键词:IsNull,IsNotNull,Like,NotLike,Containing%,In,NotIn,IgnoreCase,Between,Equal,LessThan,GreaterThan,After,Before...

排序方向:Asc,Desc

连接词:And,Or

2)嵌套实体方法命名规则:主实体中子实体的名称+_+子实体的属性名称。

排序:在方法名中添加OrderByDesc/Ase,或者设置最后一个方法参数为Sort类型。

分页:在方法中添加Pageable参数,在调用方法时传入PageRequest实现类。

 

三、Spring Data JPA实体详解

1.JPA实体概念

JPA提供了一种简单高效的方式来管理java对象到关系数据库的映射,此类Java对象称为JPA实体或,实体通常与底层数据看中的单个关系表相关联,每个实体的实例表示数据库表格中的某一行。

JPA实体的功能:

a.记录系统需要操作的数据的结构信息;

b.承载具体的数据;

c.通过实体管理器与系统交互。

2.JPA实体管理器EntityManage

用于管理系统中的实体对象,是实体与数据库之间的桥梁,通过调用实体管理器的相关方法可以把实体持久化到数据库中,同时也可以把数据库中的记录打包成实体对象。

实体生命周期:新建状态><em.persistrollback)><托管状态【实体正在被实体管理器管理】><commit.rollback/em.close/em.clear/em.detachem.merge)→游离状态【实体发生改变不会触发数据库操作】,托管状态><em.removerollback/em.persist)><删除状态,托管状态>em.refresh>托管状态。

几个重要方法:em.persist——持久化实体,插入新实体;em.merge——合并实体,修改和插入;em.remove——删除记录;find——查询实体。

@Transactional包围方法实现事务管理。

3.实体映射:实体与数据库表格之间的对应关系。

(1)基础映射:实体关系用注解来配置,@Entity用来表明某个Java类为JPA实体类,@Table实体与数据库中的哪个表关联;@Column配置字段;@Id说明Id属性;@GeneratedValue设置生成策略;@SequeceGenerator设置某列的数值生成器;@TableGenerator可以建立一个单独的表格来实现,有更好的兼容性;@SecondaryTable将实体属性分散到几个表格中存放;@Embeddable表示一个实体可以被嵌入到其他实体,在需要引入的实体中用@Embedded引入实体,并用@AttributeOverrides重新命名实体的属性名称。

(2)高级映射

一对一实体映射:主外键关系,首先让Person实体持有Address实体,@OneToOne@JoinColumn表示一对一的映射关系。

一对多实体映射:部门和员工关系,三个表的两个主外键关系,部门实体持有员工实体,@OneToMany@JoinTable表示一对多关系和中间表。或者在员工表中添加部门Id列与部门表关联,用@OneToMany@JoinColumn配置。

多对多关系:老师表和学生表,引入老师Id和学生Id组成的中间表,让老师实体持有学生实体,用@ManyToMany@JoinTable配置。

*级联问题:在OneToOne|OneToMany|ManyToManycascade选择设置如何处理重表信息(其fetch可以配置懒加载)。

4.实体继承

@Inheritance配置父类,并设置继承策略:SINGLE_TABLE(所有属性都在一张表上,并设置鉴别实体类的字段,查询效率高,但是空字段较多)|JOINED(连接表策略,避免空字段的浪费,效率较低)|TABLE_PER_CLASS(每个类一个表,表之间没有关联关系,查询效率高,不存在空间浪费和表连接)。

 

四、Spring Data JPA JPQL查询语言

1.JPQL

Java持久化查询语言,是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语句绑定在一起,使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL

2.JPQL运算符

基本语法规则:JPQL从实体中查询实体属性名,而SQL从表中查询字段名,【:+属性名】表示参数。

1)算术运算符:+、—、*/

2)比较运算符:=、>、<、>=、<=、<>;

3)逻辑运算符:between,like,in,is null判断普通属性为空,is empty判断类型为集合的属性为空,member of,not(表示否定),and,or

3.JPQL内置函数

1)字符串函数:concat,substring,trim(去掉空格或者前缀后缀),upper,lower,length,locate

2)日期时间函数:CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP;

3)算术函数:ABS,SQRT,MOD,SIZE(集合中的元素个数,作为函数只用在where条件中,或者【集合属性.size】的用法)。

4.分组、分页和排序

通过EntityManager对象的createQuery方法创建Query对象实例,调用Query对象的setFirstResultsetMaxResulet实现分页,从0开始计数。

排序:order by 属性名 desc|asc

分组:按一定的标准对数据进行归类,在每一类上进行计算——【select实体属性 聚合函数(实体属性)from实体group by实体属性having条件】,常用聚合函数avg(distinct...),sum(distinct...),count(distinct...),min,max

*语句顺序:where+group by+having+order by

wherehaving的区别:执行顺序不同,having后面可以接聚合函数,而where不能接聚合函数。

5.连接查询

1left join是以左表的记录为准的,左表的记录会全部显示出来,而右表只会显示符合搜索条件的记录,记录不足的地方均为NULL

2inner join不以那个表为基础,只显示符合条件的记录。

6.动态化JPQL查询

1)基于位置或名称的参数绑定:【?序号】或者【:名称】,设置参数时setParameter中传递序号或者名称字符串。

2)查询中使用构造器,实现返回实体或者属性列表;

3)本地化查询:直接书写原生的SQL语句,EntityManager对象的createNativeQuery方法,可以实现十分复杂的查询,但是需要对查询结果进行实体映射处理,并且不能跨数据库。