# JpaAssist JPA工具
MornBoot提供JPA相关辅助功能,以简化JPA标准查询的开发工作。JPA标准查询封装度很高,有利于封装和重用,但代码冗长,可读性较低,而JPA Assist使JPA变得简洁、高效。
Since:v1.0.0
SpringDataJPA标准查询围绕关键接口
JpaSpecificationExecutor<T>
和Specification<T>
进行,主要构建Specification<T>
对象后,调用JpaSpecificationExecutor<T>
相关查询接口完成。JPA Assist的主要职责就是极简方式构建Specification<T>
对象。
# 必要配置
Maven
<!--Spring Boot Data JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${boot.version}</version>
</dependency>
<!--Morn JPA Assist-->
<dependency>
<groupId>site.morn.boot</groupId>
<artifactId>morn-boot-jpa</artifactId>
<version>${morn.version}</version>
</dependency>
# Test Entity & Repository
@Data
@Entity
public class TestUser {
@Id
@GeneratedValue
private Long id;
@Column
private String username;
@Column
private String password;
}
public interface TestUserRepository extends CrudRepository<TestUser, Long>,
JpaSpecificationExecutor<TestUser> {
}
# Model Query
基于实体模型获取属性和值,生成查询条件
# Test User Data
{
"id": 1,
"username": "timely-rain",
"password": null
}
# Equal All
JpaBatchCondition#equalAll()
会检索实体类中的所有属性和值,并生成两者的equal
条件。若无法属性/值中的一者,则忽略该属性。
@Autowired
private TestUserRepository repository;
private List<TestUser> equalAll(TestUser user) {
// 构建查询条件
SpecificationFunction specificationFunction = (reference, restrain, condition) -> {
// WHERE id = 1 AND username = 'timely-rain'
// password为空,所以忽略
Predicate[] equalAll = condition.equalAll();
restrain.appendAnd(equalAll);
};
Specification<TestUser> specification = SpecificationBuilder.withParameter(user)
.specification(specificationFunction);
return repository.findAll(specification);
}
# Data Query
很多情况下,Entity
无法携带特殊的数据格式,而@Transient
会让实体类变得冗长。因此,JPA Assist
提供Map的传参形式。
# Test Attach Data
{
"keywords": "timely"
}
# Contain
JpaCondition#contain(String name, String valueName)
对应SQL的LIKE %something%
,name
引用实体类属性,而valueName
引用model
中的值,若model
中不存在该值时,则从attach
中获取。
@Autowired
private TestUserRepository repository;
private List<TestUser> contains(TestUser user, CriteriaMap attach) {
SpecificationFunction specificationFunction = (reference, restrain, condition) -> {
// WHERE id = 1
// password为空,所以忽略
Predicate[] equals = condition.equals("id", "password");
// AND username LIKE '%timely%'
Predicate keywords = condition.contain("username", "keywords");
restrain.appendAnd(restrain.mergeAnd(equals), keywords);
};
Specification<TestUser> specification = SpecificationBuilder.withParameter(user, attach)
.specification(specificationFunction);
return repository.findAll(specification);
}
# JPA Query
JPA Assist
目前的API并不多,有些时候仍需要使用JPA原生API。对比Model Query
,这里的代码明显多了不少。
public void equals() {
// 构建查询条件
SpecificationFunction specificationFunction = (reference, restrain, condition) -> {
Root root = reference.root();
CriteriaBuilder builder = reference.builder();
// WHERE id = 1
if (Objects.nonNull(user.getId())) {
Predicate id = builder.equal(root.get("id"), user.getId());
restrain.appendAnd(id);
}
// AND username = 'timely-rain'
if (!StringUtils.isEmpty(user.getUsername())) {
Predicate username = builder.equal(root.get("username"), user.getUsername());
restrain.appendAnd(username);
}
};
Specification<TestUser> specification = SpecificationBuilder.withParameter(user)
.specification(specificationFunction);
repository.findAll(specification);
}
# API Condition
/**
* 等于
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#equal(Expression, Object)
*/
Predicate equal(String name);
/**
* 等于
*
* @param name 实体属性名称
* @param valueName 数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#equal(Expression, Object)
*/
Predicate equal(String name, String valueName);
/**
* 不等
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#notEqual(Expression, Object)
*/
Predicate notEqual(String name);
/**
* 不等
*
* @param name 实体属性名称
* @param valueName 数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#notEqual(Expression, Object)
*/
Predicate notEqual(String name, String valueName);
/**
* 在...内
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see Expression#in(Object...)
*/
Predicate in(String name);
/**
* 包含
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#like(Expression, String)
*/
Predicate contain(String name);
/**
* 包含
*
* @param name 实体属性名称
* @param valueName 数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#like(Expression, String)
*/
Predicate contain(String name, String valueName);
/**
* 以...开始
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#like(Expression, String)
*/
Predicate startWith(String name);
/**
* 以...结束
*
* @param name 实体属性名称,数据属性名称
* @return 查询断言
* @see javax.persistence.criteria.CriteriaBuilder#like(Expression, String)
*/
Predicate endWith(String name);