JPA
JPA(Java Persistence API 是 Jakarta EE 提供的一套 ORM(对象关系映射)规范,用于简化 Java 应用与关系型数据库的交互。它允许开发者通过操作 Java 对象(实体类)来管理数据库,而无需编写复杂的 SQL 语句。Spring Boot data JPA 默认由 Hibernate 实现
与 JdbcTemplate 和 MyBatis 相比,使用 JPA 的感觉更像 Java 工程师,而不是 SQL 工程师,可能会有些不习惯
引入依赖
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.10'
id 'io.spring.dependency-management' version '1.1.7'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
定义实体类
@Entity 标注的 Java 类,对应数据库中的表。
@Id 标注主键
@GeneratedValue 主键 id 自动生成策略:
AUTO(默认,由 JPA 实现选择)
IDENTITY(数据库自增)
SEQUENCE(序列,如 Oracle 序列)
TABLE(使用单独的表维护主键)
@Column(name = "name") 定义列,可用 name 定义列名
@Data
@Entity
public class People {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
}
定义接口,继承 JpaRepository ,后面两个范型分别定义实体类和主键类型
@Repository
public interface PeopleRepository extends JpaRepository<People, Long> {
}
JpaRepository 是核心接口之一,继承了很多基础接口
Repository (标记接口)
└─ CrudRepository (基础CRUD操作)
└─ PagingAndSortingRepository (分页和排序)
└─ JpaRepository (JPA特定扩展)
Hibernate 会为我们实现接口,里面的方法可以直接用,如:
// 保存实体
<S extends T> S save(S entity);
<S extends T> List<S> saveAll(Iterable<S> entities);
// 查询方法
Optional<T> findById(ID id);
boolean existsById(ID id);
List<T> findAll();
List<T> findAllById(Iterable<ID> ids);
long count();
// 删除方法
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<ID> ids);
void deleteAll();
配置 jpa
spring.jpa.hibernate.ddl-auto
- none 默认值,不执行任何DDL操作,生产环境使用
- validate 启动时验证实体类与数据库表结构是否匹配,不匹配时会抛出异常
- update 比较实体与数据库表结构差异,只更新新增的列和表。不会删除列或表,不会修改现有列的数据类型
- create 每次启动删除所有表后重新创建,会丢失所有数据,完全根据实体类定义重建表结构
- create-drop 类似create,但在应用关闭时删除所有表
spring.jpa.show-sql 打印 sql ,方便测试,生产环境可以关闭
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://ip:port/defaultdb?sslmode=require
username: user
password: passwd
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
启动项目,会自动根据 entity 建表
Hibernate:
create table people (
id bigint generated by default as identity,
name varchar(255),
primary key (id)
)
简单测试
//插入(会返回带 id 的原对象,不会返回插入的行数)
People people = peopleRepository.save(people);
//查找所有
List<People> list = peopleRepository.findAll();
//根据id查找
Optional<People> byId = peopleRepository.findById(1L);
//根据id删除(返回 void ,不会返回删除的行数)
peopleRepository.deleteById(1L);
新建一个实体类,定义一对多关系
@OneToMany 定义一对多关系,也就是多个其他实体类指向这个实体类
mappedBy:指定关联属性的名称
cascade:级联操作类型(ALL, PERSIST, MERGE, REMOVE, REFRESH, DETACH)
orphanRemoval:是否自动删除不再被引用的子实体(默认为false)
fetch:加载策略(LAZY 或 EAGER)
@ManyToOne 定义多对一
fetch:加载策略(建议始终使用 LAZY)
targetEntity:关联的目标实体类(通常可省略)
@Entity
public class People {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "people", cascade = CascadeType.ALL, orphanRemoval = true)
List<Post> posts;
}
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name = "title")
String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "people_id")
People people;
}
插入数据,post 也会被插入
var post1 = Post.builder()
.title("title1")
.build();
var post2 = Post.builder()
.title("title2")
.build();
var people = People.builder()
.name("jeff")
.posts(List.of(post1, post2))
.build();
peopleRepository.save(people);