Spring Data JPA 入门实战笔记
相关概念
ORM思想
- Object-Relational Mapping 表示对象关系映射,在面向对象的软件开发中,通过ORM,就可以把对象映射到关系型数据库中。
- 主要目的:
操作实体类就相当于操作数据库表,不再重点关注sql语句 - 建立两个映射关系:
实体类和表的映射关系
实体类中属性和表中字段的映射关系 - 实现了ORM思想的框架:
Mybatis、Hibernate
Hibernate框架
- 一个开放源代码的对象关系映射框架
- 对JDBC进行了非常轻量级的对象封装
- 将POJO与数据库表建立映射关系,是一个全自动的ORM框架
JPA规范
-
JPA的全称是Java Persistence API, 即Java持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成。
-
JPA通过JDK 5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
-
优点:
①标准化
任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
②容器级特性支持
JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。
③简单方便
在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用javax.persistence.Entity
进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。
④ 查询能力
JPA的查询语言是面向对象而非面向数据库的,JPA定义了独特的JPQL(Java Persistence Query Language)
,它是针对实体的一种查询语言,操作对象是实体,能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
⑤高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。 -
JPA与hibernate的关系
JPA规范本质上就是一种ORM规范,注意不是ORM框架——JPA并未提供ORM实现,它只是制订了规范,提供了编程的API接口,具体实现则由服务厂商来提供。JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。
Spring Data JPA概述
- Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。
- 它提供了包括增删改查等在内的常用功能,且易于扩展,可以极大提高开发效率。
- Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。
Spring Data JPA的特性
- 极大简化了数据库访问层代码。
- Dao层中只需要写接口,就自动具有了增删改查、分页查询等方法。
快速入门案例
搭建 Spring Boot 环境
首先从 https://start.spring.io/ 构建一个Gradle的 SpringBoot 工程,选择的组件包括Lombok、 Spring Data JPA 、Web 、MySQL。
下载之后解压,先使用记事本打开 build.gradle
,在 repositories
添加以下配置:
mavenLocal()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
之后使用 IDEA 打开 build.gradle
:
完整 build.gradle
配置文件:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.sjh'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenLocal()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
定义一个测试的 Controller:
@RestController
@RequestMapping("/test")
public class TestController {
@RequestMapping("/hello")
public String hello(){
return "HELLO SPRING BOOT";
}
}
找到 src/main/java
下的 SpringBoot 启动类,由于此时还没有配置数据库,需要对@SpringBootApplication
注解添加忽视数据库配置的属性(在配置数据库信息后要取消):
@SpringBootApplication(exclude= {
DataSourceAutoConfiguration.class})
public class SpringdatajpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringdatajpaApplication.class, args);
}
}
然后启动该类,访问localhost:8080/test/hello
:
此时 Spring Boot 的环境已经成功搭建了。
创建数据库表
/*创建客户表*/
CREATE TABLE customer (
cust_id BIGINT(32) PRIMARY KEY AUTO_INCREMENT COMMENT '客户编号(主键)',
cust_name VARCHAR(32) NOT NULL COMMENT '客户名称(公司名称)',
cust_source VARCHAR(32) DEFAULT NULL COMMENT '客户信息来源',
cust_industry VARCHAR(32) DEFAULT NULL COMMENT '客户所属行业',
cust_level VARCHAR(32) DEFAULT NULL COMMENT '客户级别',
cust_address VARCHAR(128) DEFAULT NULL COMMENT '客户联系地址',
cust_phone VARCHAR(64) DEFAULT NULL COMMENT '客户联系电话'
);
配置数据库信息
在 src/main/resources
下新建 application.yml
配置文件:
spring:
datasource:
url: jdbc:mysql:///test?characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: sjh2019
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
创建实体类
@Table
关联实体类和表
@Column
关联实体类属性和表中字段
@Getter@Setter//Lombok的注解,自动生成getter、setter方法
@Entity//表明是一个实体类
@Table(name = "customer")
public class Customer {
@Id//声明主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//配置主键生产策略
@Column(name = "cust_id")
private Long id;//主键
@Column(name = "cust_name")
private String name;//名称
@Column(name = "cust_source")
private String source;//来源
@Column(name = "cust_industry")
private String industry;//行业
@Column(name = "cust_level")
private String level;//级别
@Column(name = "cust_address")
private String address;//地址
@Column(name = "cust_phone")
private String phone;//联系方式
}
@Table
注解报错其实是不影响正常执行的,如果要解决该问题,只需要配置一下IDEA的Database即可:
编写持久层接口
只需要继承 JpaRepository 即可,泛型参数列表中第一个参数是实体类类型,第二个参数是主键类型。
public interface CustomerRepo extends JpaRepository<Customer,Long> {
}
查询
根据 id 查询
@RunWith(SpringRunner.class)
@SpringBootTest
public class CustomerRepoTest {
@Autowired
private CustomerRepo customerRepo;
@Test
public void findById(){
Optional<Customer> customer = customerRepo.findById(1L);
System.out.println(customer);
}
}
结果(需要事先插入一些测试数据):
查询所有
@Test
public void findAll(){
List<Customer> customers = customerRepo.findAll();
System.out.println(customers);
}
由于只插入了一条测试数据,结果仍然只有一条,但是可以发现 SQL 语句是不同的,不再有 WHERE 筛选:
添加和修改
添加
如果添加对象的 id 在表中还不存在,会执行添加操作。
@Test
public void save(){
Customer customer = new Customer();
customer.setId(3L