1、什么是Spring Data JPA?
Spring Data JPA 是 Spring 框架的一个子项目,它简化了基于 JPA (Java Persistence API) 的数据访问层的实现。它通过减少样板代码和提供默认实现,让开发者能够更快速地构建数据访问层。
1.1、主要特点
- 减少样板代码:自动生成常见的 CRUD 操作实现
- 方法名查询:通过方法命名约定自动生成查询
- 自定义查询:支持 JPQL 和原生 SQL 查询
- 分页和排序:内置支持分页和排序功能
- 审计支持:自动记录创建时间、修改时间等
- 与 Spring 生态集成:无缝集成 Spring 事务管理等
1.2、核心接口
Repository
:标记接口,顶级接口CrudRepository
:提供基本的 CRUD 操作PagingAndSortingRepository
:扩展 CrudRepository,添加分页和排序功能JpaRepository
:JPA 特定扩展,提供 flush、批量删除等功能
2、常用的注解
2.1、实体类相关注解
@Entity
-
作用:将一个类声明为JPA实体,对应数据库中的表。
-
属性:指定实体名称,默认为类名
@Table
- 作用:指定实体对应的数据库表信息。
- 属性:
name
:表名(默认与实体类名相同)schema
:数据库schemacatalog
:数据库cataloguniqueConstraints
:唯一约束
@Id
- 作用:该注解表明该属性字段是一个主键,该属性必须具备,不可缺少。
@GeneratedValue
-
作用:指定主键生成策略。
-
属性:
-
strategy
:生成策略(GenerationType.AUTO/IDENTITY/SEQUENCE/TABLE)1、GenerationType.IDENTITY 该注解由数据库自动生成,主键自增型,在 mysql 数据库中使用最频繁,oracle 不支持。
2、GenerationType.AUTO 主键由程序控制,默认的主键生成策略,oracle 默认是序列化的方式,mysql 默认是主键自增的方式。
3、GenerationType.SEQUENCE 根据底层数据库的序列来生成主键,条件是数据库支持序列,Oracle支持,Mysql不支持。
4、GenerationType.TABLE 使用一个特定的数据库表格来保存主键,较少使用。
-
generator
:生成器名称
-
@Column
- 作用:定义字段与列的映射关系。
- 属性:
name
:列名nullable
:是否允许为nullunique
:是否唯一length
:长度(String类型)precision
:精度(BigDecimal)scale
:小数位数columnDefinition
:列定义SQL片段
@Transient
-
作用:标记字段不持久化到数据库
-
示例:
@Transient private String tempValue;
@Enumerated
-
作用:定义枚举类型的存储方式
-
属性:
value
:EnumType.ORDINAL(存储序号)或STRING(存储名称)
-
示例:
@Enumerated(EnumType.STRING) private UserStatus status;
@CreatedDate
-
作用:自动记录创建时间(每次insert的时候,会添加时间进去)
-
示例:
@CreatedDate @Column(name = "create_time") private LocalDateTime createTime;
@LastModifiedDate
-
作用:自动记录最后修改时间(每次update的时候,会添加时间进去)
-
示例:
@LastModifiedDate @Column(name = "update_time") private LocalDateTime updateTime;
@CreatedBy
-
作用:自动记录创建人
-
示例:
@CreatedBy @Column(name = "created_by") private String createdBy;
@LastModifiedBy
-
作用:自动记录最后修改人
-
示例:
@LastModifiedBy @Column(name = "modified_by") private String modifiedBy;
2.2、关联关系注解
@OneToOne
- 作用:定义一对一关系
- 属性:
mappedBy
:指定关系的维护方cascade
:级联操作类型fetch
:加载策略(FetchType.EAGER/LAZY)
@OneToMany
- 作用:定义一对多关系
- 属性:
mappedBy
:指定关系的维护方cascade
:级联操作类型fetch
:加载策略(FetchType.EAGER/LAZY)
@ManyToOne
- 作用:定义多对一关系
- 属性:
mappedBy
:指定关系的维护方cascade
:级联操作类型fetch
:加载策略(FetchType.EAGER/LAZY)
@ManyToMany
- 作用:定义多对多关系
- 属性:
mappedBy
:指定关系的维护方cascade
:级联操作类型fetch
:加载策略(FetchType.EAGER/LAZY)
2.3、查询方法注解
@Query
-
作用:定义自定义JPQL或原生SQL查询
-
属性:
value
:JPQL/SQL查询语句nativeQuery
:是否为原生SQL(默认false)countQuery
:分页查询时统计总数的查询
-
示例:
@Query("SELECT u FROM User u WHERE u.email = ?1") User findByEmail(String email);
@Modifying
-
作用:标识修改数据的查询(UPDATE/DELETE) 自定义修改数据时,返回值必须为 void 或者 int/Integer!
-
属性:
clearAutomatically
:执行后是否自动清除持久化上下文flushAutomatically
:执行前是否自动flush
-
示例:
@Modifying @Query("UPDATE User u SET u.status = ?2 WHERE u.id = ?1") int updateUserStatus(Long id, String status);
@EntityGraph
- 作用:定义实体图的加载策略,解决N+1查询问题
- 属性:
attributePaths
:要立即加载的属性路径type
:加载类型(EntityGraphType.FETCH/LOAD)
3、简单的Demo创建
3.1、引入依赖
<!-- Spring Data JPA 依赖(重要) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL 驱动(重要) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实体类插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3.2、配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springbootjpa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: ys_nj_sst!
jpa:
hibernate:
# 控制是否可以基于程序中Entity的定义自动创建或者修改DB中表结构
ddl-auto: update
# 是否打印运行时的sql
show-sql: true
3.3、实体映射Entity
@Entity
@Data
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,unique = true,length = 20)
private String username;
@Column(nullable = false,length = 20)
private String password;
@Column(nullable = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")//返回格式化
private Date regdate;
@Transient
private String remark;
}
3.4、定义Dao层
public interface UserRepository extends JpaRepository<User,Long> {
@Query(value = "select * from user u where u.id = ?1",nativeQuery = true)
User findUserById(@Param("id") Long id);
/*
* 注意:jpa手写更新语句时,返回值必须为void 或者 int/Integer
*/
@Transactional
@Modifying
@Query(value = "update user set username = ?2,password = ?3 where id = ?1",nativeQuery = true)
Integer update(Long id,String username,String password);
/*
* 不使用本地查询
*/
@Query(value = "select u from User u where u.username like %:username%")
List<User> findByNameMatch(@Param("username") String username);
}