Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 JPA 技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增、删、改、查等在内的常用功能,易于扩展,极大提高开发效率。
Spring Data Common 是 Spring Data 所有模块的公共部分,该项目提供了基于 Spring 的共享基础设施,它提供了基于 repository 接口以 DB 操作的一些封装,以及一个坚持在 Java 实体类上标注元数据的模型。
Spring Data 不仅对传统的数据库访问技术如 JDBC、Hibernate、JDO、TopLick、JPA、MyBatis 做了很好的支持和扩展、抽象、提供方便的操作方法,还对 MongoDb、KeyValue、Redis、LDAP、Cassandra 等非关系数据的 NoSQL 做了不同的实现版本,方便我们开发者触类旁通。
Redis
、MongoDB
等NoSQL的操作,他们底层依赖了统一的 Spring Data Common
。Spring Data和JPA的结构关系:
3、项目集成
外部依赖:
Spring Boot 已经为 JPA 封装了starter组件,只需在 pom.xml 文件中添加jar版本依赖即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
Spring Boot Starter Data JPA 依赖 Spring Data JPA;而 Spring Data JPA 依赖 Spring Data Commons。
配置文件:
在配置文件 application.yaml 中配置 JPA 的相关参数,具体内容如下:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ds0?characterEncoding=utf-8
username: root
password: 111111
# Hikari config
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 200
idle-timeout: 60000
pool-name: MarketingHikariCP
max-lifetime: 1800000
connection-timeout: 2000
connection-test-query: select 1
jpa:
show-sql: true #在控制台打印 sql 语句
数据库连接用的是 JDBC,连接池用的是 HikariCP,强依赖 Hibernate;
工程结构如图所示:
定义实体对象:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
public class User {
@Id // @Id注解指明这个属性映射为数据库的主键。
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 名称
private String userName;
// 年龄
private Integer age;
// 地址
private String address;
}
注解说明:
数据访问层 UserRepository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUserName(String userName);
List<User> findByUserNameAndAddress(String userName, String address);
// 使用 @Query查询,参数按照名称绑定
@Query("select u from User u where u.userName= :userName and u.address= :address")
List<User> queryByUserNameAndAddress(@Param("userName") String userName, @Param("address") String address);
}
层次结构类图:
UserRepository
接口继承 JpaRepository
,JpaRepository
继承了接口PagingAndSortingRepository
和QueryByExampleExecutor
。而PagingAndSortingRepository
又继承CrudRepository
。
除了使用继承系统提供的扩展接口类外,还可以采用约定规则方式。
自定义的简单查询就是根据方法名来自动生成SQL,具体是方法名以 findBy、existsBy、countBy、deleteBy
开头,后面跟具体的条件,举几个例子:
关键字 | 方法示例 | JPQL snippet |
---|---|---|
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.firstame) = UPPER(?1) |
Spring Data JPA 已经帮我们实现了分页,在查询的方法中,需要传入参数PageRequest
,当查询中有多个参数的时候PageRequest
建议做为最后一个参数传入。PageRequest
是 spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则
@RequestMapping("/page")
public Page<User> page(@RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize) {
Page<User> pageUser = userRepository.findAll(new PageRequest(pageNo, pageSize));
return pageUser;
}
Spring data 大部分的 SQL 都可以根据方法名定义的方式来实现,但是有些复杂业务场景需要使用自定义的 SQL 来查询,spring data 也是支持的。
@Query("select u from User u where u.userName= :userName and u.address= :address")
List<User> queryByUserNameAndAddress(@Param("userName") String userName, @Param("address") String address);
https://github.com/aalansehaiyang/spring-boot-bulking
模块:spring-boot-bulking-data-jpa