Spring Data JPA 框架
简介
Spring Data Jpa 是应⽤于Dao层的⼀个框架,简化数据库开发的,作⽤和Mybatis框架⼀样,但是在使
⽤⽅式和底层机制是有所不同的。最明显的⼀个特点,Spring Data Jpa 开发Dao的时候,很多场景我们
连sql语句都不需要开发。由Spring出品。
Spring Data JPA 是 Spring 基于JPA 规范的基础上封装的⼀套 JPA 应⽤框架,可使开发者⽤极简的
代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常⽤功能!学习并使⽤
Spring Data JPA 可以极⼤提⾼开发效率。
说明:Spring Data JPA 极⼤简化了数据访问层代码。
如何简化呢?使⽤了Spring Data JPA,我们Dao层中只需要写接⼝,不需要写实现类,就⾃动具有
了增删改查、分⻚查询等⽅法。
使⽤Spring Data JPA 很多场景下不需要我们⾃⼰写sql语句
JPA规范和Hibernate之间的关系
Spring Data JPA 是 Spring 提供的⼀个封装了JPA 操作的框架,⽽ JPA 仅仅是规范,单独使⽤规范⽆法
具体做什么,那么Spring Data JPA 、 JPA规范 以及 Hibernate (JPA 规范的⼀种实现)之间的关系是什
么?
image
JPA 是⼀套规范,内部是由接⼝和抽象类组成的,Hiberanate 是⼀套成熟的 ORM 框架,⽽且
Hiberanate 实现了 JPA 规范,所以可以称 Hiberanate 为 JPA 的⼀种实现⽅式,我们使⽤ JPA 的 API 编
程,意味着站在更⾼的⻆度去看待问题(⾯向接⼝编程)。
Spring Data JPA 是 Spring 提供的⼀套对 JPA 操作更加⾼级的封装,是在 JPA 规范下的专⻔⽤来进⾏数
据持久化的解决⽅案。
Spring Data JPA 常用注解
1.@Entity:标识实体类是JPA实体,告诉JPA在程序运行时生成实体类对应表
2.@Table:设置实体类在数据库所对应的表名
3.@Id:标识类里所在变量为主键
4.@GeneratedValue:设置主键生成策略,此方式依赖于具体的数据库
5.@Column:表示属性所对应字段名进行个性化设置
6.@Transient:表示属性并非数据库表字段的映射,ORM框架将忽略该属性
7.@Temporal:(很重要)
当我们使用到java.util包中的时间日期类型,则需要此注释来说明转化成java.util包中的类型。
注入数据库的类型有三种:
TemporalType.DATE(2008-08-08)
TemporalType.TIME(20:00:00)
TemporalType.TIMESTAMP(2008-08-08 20:00:00.000000001)
8.@Enumerated:(很重要)
使用此注解映射枚举字段,以String类型存入数据库
注入数据库的类型有两种:EnumType.ORDINAL(Interger)、EnumType.STRING(String)
9.@Embedded、@Embeddable:
当一个实体类要在多个不同的实体类中进行使用,而其不需要生成数据库表
@Embeddable:注解在类上,表示此类是可以被其他类嵌套
@Embedded:注解在属性上,表示嵌套被@Embeddable注解的同类型类
10.@ElementCollection:集合映射
11.@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy:(很重要)
表示字段为创建时间字段(insert自动设置)、创建用户字段(insert自动设置)、最后修改时间字段(update自定设置)、最后修改用户字段(update自定设置)
用法:
1、@EntityListeners(AuditingEntityListener.class):申明实体类并加注解`
2 、实现AuditorAware类
3、springboot 启动类加上注解@EnableJpaAuditing
4、在实体类中属性中加上面四种注解
后续会写个这个的demo
12.@MappedSuperclass:(很重要)
实现将实体类的多个属性分别封装到不同的非实体类中
注解的类将不是完整的实体类,不会映射到数据库表,但其属性将映射到子类的数据库字段
注解的类不能再标注@Entity或@Table注解,也无需实现序列化接口
注解的类继承另一个实体类 或 标注@MappedSuperclass类,他可使用@AttributeOverride 或 @AttributeOverrides注解重定义其父类属性映射到数据库表中字段。
Spring Data JPA 使用
导入坐标
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.3.RELEASE
com.example
demo
0.0.1-SNAPSHOT
demo
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
5.1.21
com.alibaba
druid
1.1.10
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.fasterxml.jackson.core
jackson-annotations
2.9.7
org.springframework.boot
spring-boot-maven-plugin
配置 Spring 的配置⽂件
spring:
datasource:
url: jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true
username: root
password: root
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
filters: stat
initialSize: 1
minIdle: 3
maxActive: 20
# 配置获取连接等待超时的时间showBussMonthRentReport
maxWait: 10000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 10000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20 # 指定每个连接上PSCache的大小
jpa:
hibernate:
ddl-auto: update # 第一次建表create 后面用update,要不然每次重启都会新建表
show-sql: true #打印执行的sql语句
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect #设置数据库方言 记住必须要使用 MySQL5InnoDBDialect 指定数据库类型对应InnoDB ;如果使用MySQLDialect 则对应的是MyISAM
编写实体类,使⽤ JPA 注解配置映射关系
package com.example.demo.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
@Setter
@Getter
@ToString
@Entity
@Table(name = "hot")
public class Hot {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "requirements")
private String requirements;
@Column(name = "salary")
private String salary;
@Column(name = "company_name")
private String companyName;
@Column(name = "company_label")
private String companyLabel;
@Column(name = "company_logo")
private String companyLogo;
@Transient
private String company;
}
编写 接⼝
package com.example.demo.dao;
import com.example.demo.model.Hot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* ⼀个符合SpringDataJpa要求的Dao层接⼝是需要继承JpaRepository和
JpaSpecificationExecutor
*
* JpaRepository
* 封装了基本的CRUD操作
*
* JpaSpecificationExecutor
* 封装了复杂的查询(分⻚、排序等)
*
*/
public interface HotDao extends JpaRepository, JpaSpecificationExecutor {
@Query("from Resume where id=?1 and name=?2")
public List findByJpql(Long id,String name);
/**
* 使⽤原⽣sql语句查询,需要将nativeQuery属性设置为true,默认为false(jpql)
* @param name
* @param companyName
* @return
*/
@Query(value = "select * from tb_resume where name like ?1 and
company_name like ?2",nativeQuery = true)
public List findBySql(String name,String companyName);
/**
* ⽅法命名规则查询
* 按照name模糊查询(like)
* ⽅法名以findBy开头
* -属性名(⾸字⺟⼤写)
* -查询⽅式(模糊查询、等价查询),如果不写查询⽅式,默认等价
查询
*/
public List findByNameLikeAndCompanyName(String name,String
companyName);
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
@Autowired
private HotDao hotDao;
@Test
void contextLoads() {
Hot hot= new Hot();
hot.setCompanyName("peng");
hotDao.saveAndFlush(hot);
}
}
分析
/**
* ========================针对查询的使⽤进⾏分析=======================
* ⽅式⼀:调⽤继承的接⼝中的⽅法 findOne(),findById()
* ⽅式⼆:可以引⼊jpql(jpa查询语⾔)语句进⾏查询 (=====>>>> jpql 语句类似于
sql,只不过sql操作的是数据表和字段,jpql操作的是对象和属性,⽐如 from Resume where
id=xx) hql
* ⽅式三:可以引⼊原⽣的sql语句
* 规则查询,也就是说定义的接⼝⽅法名是按照⼀定规则形成的,那么框架就能够理解我们的意图
* * ⽅式五:动态查询
* * service层传⼊dao层的条件不确定,把service拿到条件封装成⼀个对象传递给
* Dao层,这个对象就叫做Specification(对条件的⼀个封装)
* *
* *
* * // 根据条件查询单个对象
* * Optional findOne(@Nullable Specification var1);
* * // 根据条件查询所有
* * List findAll(@Nullable Specification var1);
* * // 根据条件查询并进⾏分⻚
* * Page findAll(@Nullable Specification var1, Pageable
* var2);
* * // 根据条件查询并进⾏排序
* * List findAll(@Nullable Specification var1, Sort
* var2);
* * // 根据条件统计
* * long count(@Nullable Specification var1);
* *
* * interface Specification
* * toPredicate(Root var1, CriteriaQuery> var2,
* CriteriaBuilder var3);⽤来封装查询条件的
* * Root:根属性(查询所需要的任何属性都可以从根对象中获取)
* * CriteriaQuery ⾃定义查询⽅式 ⽤不上
* * CriteriaBuilder 查询构造器,封装了很多的查询条件(like =
* 等)
* *
* *
* */