一.概述

Spring Data JPA:是Spring Data 系列的一部分,可以轻松实现基于 JPA 的操作数据库。该模块处理对基于 JPA 的数据访问层的增强支持。它使构建使用数据访问技术的 Spring 驱动的应用程序变得更加容易。
JPA:Java Persistence API Java持久层API技术,Java中提供的一套操作数据库的API接口,就是使用注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
优点:
1.支持多种操作数据库的方式
2.根据实体类 ,自动生成DDL语句
3.支持面向对象查询语言(JPQL)
4.内部封装常用的CRUD方法
5.对应简单操作,支持方法名解析查询

二.快速入门

1.导包

  1. <dependencies>
  2. <dependency>
  3. <groupId>mysql</groupId>
  4. <artifactId>mysql-connector-java</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba</groupId>
  8. <artifactId>druid</artifactId>
  9. <version>1.2.6</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-data-jpa</artifactId>
  14. </dependency>
  15. <dependency>
  16. <groupId>junit</groupId>
  17. <artifactId>junit</artifactId>
  18. <scope>test</scope>
  19. </dependency>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-test</artifactId>
  23. </dependency>
  24. </dependencies>

2.配置

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://39.105.189.141:3307/db_j215data?characterEncoding=UTF-8
  4. driver-class-name: com.mysql.cj.jdbc.Driver
  5. username: root
  6. password: zzjava
  7. type: com.alibaba.druid.pool.DruidDataSource
  8. initialSize: 5
  9. minIdle: 5
  10. maxActive: 20
  11. maxWait: 60000
  12. logSlowSql: true
  13. jpa:
  14. database: MySQL
  15. show-sql: true
  16. hibernate:
  17. ddl-auto: update

3.代码

(1)实体类

  1. @Data
  2. @Entity //JPA 标记这是个数据库表的映射类
  3. @Table(name = "t_project_group") //标记映射类对应的数据库表名,如果一致,可以省略
  4. public class ProjectGroup {
  5. @Id //修饰属性,标记主键字段对应的属性
  6. @GeneratedValue(strategy = GenerationType.IDENTITY)//标记主键的生成策略,指定自增
  7. private Integer id;
  8. private String name;
  9. private String leaderName;
  10. private String projectName;
  11. }

(2)持久层

  1. //继承默认接口,JpaRepository,双泛型:
  2. //1.持久层对应的映射类名
  3. //2.注解的数据类型 。默认提供了常用的单表操作方法
  4. public interface ProjectGroupDao extends JpaRepository<ProjectGroup,Integer> {
  5. }

(3)单元测试

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @SpringBootTest(classes = DataJpaApplication.class)
  3. public class JPATest {
  4. @Autowired
  5. private ProjectGroupDao dao;
  6. //新增或者修改 主键存在修改 ,不存在就是新增
  7. @Test
  8. public void t1(){
  9. ProjectGroup g1=new ProjectGroup();
  10. g1.setLeaderName("李源2");
  11. g1.setName("第一组");
  12. g1.setProjectName("Keep");
  13. //新增
  14. System.err.println(dao.save(g1));
  15. }
  16. //查询数据
  17. @Test
  18. public void t2(){
  19. System.err.println(dao.findAll());
  20. }
  21. //删除
  22. @Test
  23. public void t3(){
  24. dao.deleteById(2);
  25. System.err.println(dao.findAll(Sort.by(Sort.Order.desc("id"))));
  26. }
  27. }

三.核心

1.Spring Data JPA重点

1.实体类
需要记忆的注解
@Entity :修饰类,标记这是个数据库表的映射类
@Table(name = “表名”) :修饰类,标记映射类对应的数据库 表名,如果一致,可以省略
@Id :修饰属性,标记主键字段对应的属性
@GeneratedValue(strategy = GenerationType.IDENTITY):修饰属性,标记主键的生成策略,指定自增,一般配合@Id使用
@Column(length = 长度) :修饰属性,标记属性对应的数据库表的字段信息
2.持久层
_默认的接口:_JpaRepository<映射类的名称,主键的数据类型>
JpaRepository默认提供单表的常用操作,CRUD page sort等
3.开关类
映射层的扫描:@EntityScan(basePackages = “映射类所在的包名”)
4.Spring Data JPA的配置

  1. spring:
  2. jpa:
  3. database: MySQL
  4. show-sql: true
  5. hibernate:
  6. ddl-auto: update

2.核心操作:

(1)接口式操作

JpaRepository 提供了默认的常用的单表操作的各种方法,默认自动生成对应的sql语句

(2)JPQL查询

JPQL:面向对象查询语言,跟SQL语句完全不一样,采用面向对象的思维,来操作数据库
表—-类,字段—-类中属性,一条数据—-对象
比如:
sql:select * from 表名 Jpql: from 类名 或者 select new 类名(属性名,……) from 类名
字段换成类的属性,表名换成类名。

(3)方法名解析查询

提供了一种,规则,去定义方法名,可以根据此规则,逆向解析方法名,从而自动生成sql语句
比如:findById(int id)—-方法名解析—- select from 表名 where id=xxx
findByNameLikeAndId—-方法名解析—select
from 表名 where name like ‘’ and id=xx

(4)SQL查询

也支持原生SQL语句进行执行sql语句,但是需要在@Query(nativeQuery=true)
多参数的处理:?索引 的格式获取参数,索引从1开始

四、Spring Data JPA综合代码

基于代码实现Spring Data JPA的四种查询
持久层

  1. //继承默认接口,JpaRepository,双泛型:1.持久层对应的映射类名 2.注解的数据类型
  2. //默认提供了常用的单表操作方法
  3. public interface ProjectGroupDao extends JpaRepository<ProjectGroup,Integer> {
  4. //JPQL操作 表--类 字段--属性
  5. @Query("from ProjectGroup")
  6. List<ProjectGroup> all1();
  7. @Query("from ProjectGroup where leaderName like ?1")
  8. List<ProjectGroup> all3(String n);
  9. //方法名解析查询
  10. List<ProjectGroup> findByNameLike(String n);
  11. //SQL语句操作
  12. @Query(nativeQuery = true,value = "select * from t_project_group where id=?1")
  13. ProjectGroup all2(int id);
  14. }

测试

  1. //接口的操作
  2. @Test
  3. public void t4(){
  4. dao.findAll(Pageable.ofSize(1).withPage(0)).get().forEach(System.out::println);
  5. }
  6. //JPQL测试
  7. @Test
  8. public void t5(){
  9. dao.all1().forEach(System.out::println);
  10. dao.all3("%李%").forEach(System.err::println);
  11. }
  12. //方法名解析查询(方法名规则查询)
  13. @Test
  14. public void t6(){
  15. dao.findByNameLike("%三%").forEach(System.out::println);
  16. }
  17. //sql语句实现查询
  18. @Test
  19. public void t7(){
  20. System.err.println(dao.all2(3));
  21. }

五、Spring Data JPA附录

1 方法命名规则和对应的JPQL

Keyword Sample JPQL snippet
Distinct findDistinctByLastnameAndFirstname select distinct … where x.lastname = ?1 and x.firstname = ?2
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstname) = UPPER(?1)

六.注意事项

@PersistenceContext

这是jpa专有的注解,和@Autowired作用差不多,而@Autowired是spring自带的注释, 因为EntityManager不是线程安全的,当多个请求进来的时候,spring会创建多个线程,@PersistenceContext就是用来为每个线程创建一个EntityManager的,而@Autowired只创建了一个,为所有线程共用,有可能报错
在使用EntityManager的时,请采用@PersistenceContext进行注解,而不要使用@Autowired

@Transient 注解: 表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性。

EntityManager

这是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。其接口如下:
image.png

托管方式:

EntityManager托管方式由两种:容器托管(EntityManger && PersistenceContext)和应用托管(EntityManagerFactory && PersistenceUnit),比较简单的方式是采用容器托管(EJB容器)。实现方式如下:
@PersistenceContext
private EntityManager entityManager;

@Transactional(rollbackFor = {RuntimeException.class, Exception.class})

@Column(name = “CODE”)
private String code;
@Column和private String code必须有一个和数据库select 后的字段一致

返回值问题:

EntityManager.createNativeQuery(SQL)返回值类型的问题
(1)如果这样写:createNativeQuery(SQL),返回类型就是List list,
(2)如果这样写:createNativeQuery(SQL, User.class),返回类型就是List list;
但是有一个问题,就比如第二种写法,返回了指定的User类型,但是这个User类必须含有@Entity 注解, 一旦加了这个注解就会生成对应的表, 如果我们不想生成表怎么办呢,假如返回的是多表数据,可能这这个数据就用一次,在生成一个表那不是浪费了吗

使用封装的工具类,即可解决这个问题;

  1. /**
  2. * 将数组数据转换为实体类
  3. * 此处数组元素的顺序必须与实体类构造函数中的属性顺序一致
  4. *
  5. * @param list 你要转换的对象
  6. * @param clazz<T> 转换为什么类型,就是转换成什么类型的实体类
  7. * @param model 这里传入的是实例化的实体类对象,必须有全参构造
  8. * @return 实体类集合
  9. */
  10. List<T> castEntity(List<Object[]> list, Class<T> clazz, Object model);