目录
一 Specifications动态查询Specification用法findOne多条件拼接模糊匹配排序分页查询方法对应关系
一 Specifications动态查询
有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。
import java
.util
.List
;
import org
.springframework
.data
.domain
.Page
;
import org
.springframework
.data
.domain
.Pageable
;
import org
.springframework
.data
.domain
.Sort
;
import org
.springframework
.data
.jpa
.domain
.Specification
;
public interface JpaSpecificationExecutor<T> {
T
findOne(Specification
<T> spec
);
List
<T> findAll(Specification
<T> spec
);
Page
<T> findAll(Specification
<T> spec
, Pageable pageable
);
List
<T> findAll(Specification
<T> spec
, Sort sort
);
long count(Specification
<T> spec
);
}
Specification
对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。 Specification接口中只定义了如下一个方法
public Predicate
toPredicate(Root
<T> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
);
用法
findOne
public void testSpec() {
Specification
<Customer> spec
= new Specification<Customer>() {
@Override
public Predicate
toPredicate(Root
<Customer> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
) {
Path
<Object> custId
= root
.get("custId");
Predicate predicate
= cb
.equal(custId
, 3);
return predicate
;
}
};
Optional
<Customer> customer
= customerDao
.findOne(spec
);
System
.out
.println(customer
.get());
}
多条件拼接
public void testSpec1() {
Specification
<Customer> spec
= new Specification<Customer>() {
@Override
public Predicate
toPredicate(Root
<Customer> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
) {
Path
<Object> custName
= root
.get("custName");
Path
<Object> custAddress
= root
.get("custAddress");
Predicate p1
= cb
.equal(custName
, "黑马程序员");
Predicate p2
= cb
.equal(custAddress
, "hangz");
Predicate and
= cb
.and(p1
, p2
);
return and
;
}
};
Optional
<Customer> customer
= customerDao
.findOne(spec
);
System
.out
.println(customer
);
}
模糊匹配
equal :直接的到path对象(属性),然后进行比较即可gt,lt,ge,le,like : 得到path对象,根据path指定比较的参数类型,再去进行比较 指定参数类型:path.as(类型的字节码对象)
public void testSpec3() {
Specification
<Customer> spec
= new Specification<Customer>() {
@Override
public Predicate
toPredicate(Root
<Customer> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
) {
Path
<Object> custName
= root
.get("custName");
Predicate like
= cb
.like(custName
.as(String
.class), "d%");
return like
;
}
};
List
<Customer> list
= customerDao
.findAll(spec
);
for (Customer customer
: list
) {
System
.out
.println(customer
);
}
}
排序
public void testSpec3() {
Specification
<Customer> spec
= new Specification<Customer>() {
@Override
public Predicate
toPredicate(Root
<Customer> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
) {
Path
<Object> custName
= root
.get("custName");
Predicate like
= cb
.like(custName
.as(String
.class), "d%");
return like
;
}
};
Sort sort
= new Sort(Sort
.Direction
.DESC
,"custId");
List
<Customer> list
= customerDao
.findAll(spec
, sort
);
for (Customer customer
: list
) {
System
.out
.println(customer
);
}
}
分页查询
创建PageRequest的过程中,需要调用他的构造方法传入两个参数
第一个参数:当前查询的页数(从0开始)第二个参数:每页查询的数量
public void testSpec4() {
Specification
<Customer> spec
= new Specification<Customer>() {
@Override
public Predicate
toPredicate(Root
<Customer> root
, CriteriaQuery
<?> query
, CriteriaBuilder cb
) {
Path
<Object> custName
= root
.get("custName");
Predicate like
= cb
.like(custName
.as(String
.class), "d%");
return like
;
}
};
Pageable pageable
= PageRequest
.of(0,1);;
Page
<Customer> page
= customerDao
.findAll(spec
, pageable
);
System
.out
.println(page
.getContent());
System
.out
.println(page
.getTotalElements());
System
.out
.println(page
.getTotalPages());
}
方法对应关系