JPA动态查询封装
一、定义一个查询条件容器
/**
* 定义一个查询条件容器
*
* @param <T>
*/
public class Criteria<T> implements Specification<T> {
private List<Criterion> criterions = new ArrayList<Criterion>(); public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
if (!criterions.isEmpty()) {
List<Predicate> predicates = new ArrayList<Predicate>();
for(Criterion c : criterions){
predicates.add(c.toPredicate(root, query,builder));
}
// 将所有条件用 and 联合起来
if (predicates.size() > 0) {
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}
return builder.conjunction();
}
/**
* 增加简单条件表达式
* @Methods Name add
* @param
*/
public Criteria<T> add(Criterion criterion){ if(criterion!=null){
criterions.add(criterion);
} return this;
}
}
二、条件接口
public interface Criterion {
public enum Operator {
EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR
}
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder);
}
三、逻辑条件表达式,用于复杂条件时使用,如or或and
public class LogicalExpression implements Criterion {
private Criterion[] criterion; // 逻辑表达式中包含的表达式
private Operator operator; //计算符
public LogicalExpression(Criterion[] criterions, Operator operator) {
this.criterion = criterions;
this.operator = operator;
}
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
for(int i=0;i<this.criterion.length;i++){
predicates.add(this.criterion[i].toPredicate(root, query, builder));
}
switch (operator) {
case OR:
return builder.or(predicates.toArray(new Predicate[predicates.size()]));
case AND:
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
default:
return null;
}
}
}
四、简单条件表达式
public class SimpleExpression implements Criterion{
private String fieldName; //属性名
private Object value; //对应值
private Operator operator; //计算符
protected SimpleExpression(String fieldName, Object value, Operator operator) {
this.fieldName = fieldName;
this.value = value;
this.operator = operator;
}
public String getFieldName() {
return fieldName;
}
public Object getValue() {
return value;
}
public Operator getOperator() {
return operator;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
Path expression = null;
if(fieldName.contains(".")){
String[] names = StringUtils.split(fieldName, ".");
expression = root.get(names[0]);
for (int i = 1; i < names.length; i++) {
expression = expression.get(names[i]);
}
}else{
expression = root.get(fieldName);
}
switch (operator) {
case EQ:
return builder.equal(expression, value);
case NE:
return builder.notEqual(expression, value);
case LIKE:
return builder.like((Expression<String>) expression, "%" + value + "%");
case LT:
return builder.lessThan(expression, (Comparable) value);
case GT:
return builder.greaterThan(expression, (Comparable) value);
case LTE:
return builder.lessThanOrEqualTo(expression, (Comparable) value);
case GTE:
return builder.greaterThanOrEqualTo(expression, (Comparable) value);
default:
return null;
}
}
}
五、条件构造器,用于创建条件表达式
public class Restrictions {
/**
* 等于
* @param fieldName
* @param value
* @return
*/
public static SimpleExpression eq(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.EQ);
}
/**
* 不等于
* @param fieldName
* @param value
* @return
*/
public static SimpleExpression ne(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.NE);
}
/**
* 模糊匹配
* @param fieldName
* @param value
* @param
* @return
*/
public static SimpleExpression like(String fieldName, String value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.LIKE);
}
/**
* 大于
* @param fieldName
* @param value
* @return
*/
public static SimpleExpression gt(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.GT);
}
/**
* 小于
* @param fieldName
* @param value
* @return
*/
public static SimpleExpression lt(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.LT);
}
/**
* 大于等于
* @param fieldName
* @param value
* @return
*/
public static SimpleExpression lte(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.LTE);
}
/**
* 小于等于
* @param fieldName
* @param value
* @param
* @return
*/
public static SimpleExpression gte(String fieldName, Object value) {
if(StringUtils.isEmpty(value))return null;
return new SimpleExpression (fieldName, value, Criterion.Operator.GTE);
}
/**
* 并且
* @param criterions
* @return
*/
public static LogicalExpression and(Criterion... criterions){
return new LogicalExpression(criterions, Criterion.Operator.AND);
}
/**
* 或者
* @param criterions
* @return
*/
public static LogicalExpression or(Criterion... criterions){
return new LogicalExpression(criterions, Criterion.Operator.OR);
}
/**
* 包含于
* @param fieldName
* @param value
* @return
*/
@SuppressWarnings("rawtypes")
public static LogicalExpression in(String fieldName, Collection value, boolean ignoreNull) {
if(ignoreNull&&(value==null||value.isEmpty())){
return null;
}
SimpleExpression[] ses = new SimpleExpression[value.size()];
int i=0;
for(Object obj : value){
ses[i]=new SimpleExpression(fieldName,obj, Criterion.Operator.EQ);
i++;
}
return new LogicalExpression(ses, Criterion.Operator.OR);
}
/**
* 不包含于
* @param fieldName
* @param value
* @return
*/
@SuppressWarnings("rawtypes")
public static LogicalExpression notin(String fieldName, Collection value, boolean ignoreNull) {
if(ignoreNull&&(value==null||value.isEmpty())){
return null;
}
SimpleExpression[] ses = new SimpleExpression[value.size()];
int i=0;
for(Object obj : value){
ses[i]=new SimpleExpression(fieldName,obj, Criterion.Operator.NE);
i++;
}
return new LogicalExpression(ses, Criterion.Operator.AND);
}
/**
* between
* @param fieldName
* @param object1
* @param object2
* @return
*/
public static LogicalExpression between(String fieldName, Object object1, Object object2)
{
if(object1 == null || object2 == null)
{
return null;
}
SimpleExpression[]ses=new SimpleExpression[2];
ses[0]=new SimpleExpression(fieldName,object1, Criterion.Operator.GTE);
ses[1]=new SimpleExpression(fieldName,object2, Criterion.Operator.LTE);
return new LogicalExpression(ses, Criterion.Operator.AND);
}
六、构造动态查询仓库接口
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends PagingAndSortingRepository<T,ID> { int count(Specification<T> specification);
Page<T> findAll(Specification<T> specification, Pageable pageable);
List<T> findAll(Specification<T> specification);
}
使用实例:
POJO对象为
public class UserInfo
{
private Integer id;
private String name;
...
}
dao接口为
public interface UserInfoService extends BaseRepository<UserInfo,Integer>
{
}
使用:
@RunWith(SpringRunner.class)
@SpringBootTest
public class test
{
@Autowired
private UserInfoService userInfoService;
@Test
public void test()
{
Criteria<UserInfo> criteria = new Criteria<>();
criteria.add(Restrictions.eq("id",10)).add(Restrictions.like("name","abc"));
List<UserInfo> users = userInfoService.findAll(criteria);
}
}
JPA动态查询封装的更多相关文章
- SSH动态查询封装接口介绍
SSH动态查询封装接口介绍 1.查询记录总条数 public int count(Class c,Object[][] eq,Object[][] like,String[] group,String ...
- spring data jpa 动态查询(工具类封装)
利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...
- springboot整合spring data jpa 动态查询
Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个: 1.Criteria ...
- spring jpa 动态查询(Specification)
//dao层 继承 扩展仓库接口JpaSpecificationExecutor (JPA 2引入了一个标准的API)public interface CreditsEventDao extends ...
- Spring Data JPA动态查询(多条件and)
entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerat ...
- spring JPA 动态查询
没什么好说的,记住就行. 下面是在Service中的方法 Page<TStaff> staffs=dao.findAll(new Specification<TStaff>() ...
- Hibernate JPA 动态criteria语句针对null查询条件的特殊处理
最近原Hibernate项目需要添加一个条件,结构有点类似下面的格式,学生和房间是多对一的关系,现在要查询所有没有房间的学生. Class Student{ @ManyToOne Room room; ...
- spring data jpa封装specification实现简单风格的动态查询
github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...
- SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法
软件152 尹以操 首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml ...
随机推荐
- 1.5(Spring MVC学习笔记) 拦截器(Interceptor)
一.拦截器 1.1拦截器简介 Spring中的拦截器类似Servlet中的过滤器(Filter),主要用于拦截用户请求, 并进行一定的处理操作(如验证权限.记录日志.设置编码方式等). 1.2拦截器实 ...
- 6.3(java学习笔记)缓冲流
一.缓冲流 使用缓冲流后的输入输出流会先存储到缓冲区,等缓冲区满后一次性将缓冲区中的数据写入或取出. 避免程序频繁的和文件直接操作,这样操作有利于提高读写效率. 缓冲流是构建在输入输出流之上的,可以理 ...
- 个人python学习路线记录
一.入门视频 零基础入门学习Python --小甲鱼 二.博客园 python快速教程 http://www.cnblogs.com/vamei/archive/2012/09/13/2682778. ...
- Swift中计算String的长度
extension String { var length: Int { return countElements(self) } // Swift 1.1 } extension ...
- winform 窗体实现增删改查(CRUD)窗体基类模式
参考博客下方:http://www.cnblogs.com/wuhuacong/archive/2010/05/31/1748579.html 对于一般常用到的编辑数据.新增数据窗体,分开了两个不同的 ...
- mq使用经验
1.Producer使用指南--发送消息注意事项 1.正常情况下一个业务系统尽可能用一个Topic,消息子类型用tags来标识,tags可以由业务系统自由设置.只有发送消息设置了tags,消费方在订阅 ...
- webpack配置构建环境问题汇总
环境:node 6.9.5 npm 3.10.10 问题一:Module build failed: TypeError: Path must be a string. Received undef ...
- C++11的初始化列表
初始化是一个非常重要的语言特性,最常见的就是对对象进行初始化.在传统 C++ 中,不同的对象有着不同的初始化方法,例如普通数组.POD (plain old data,没有构造.析构和虚函数的类或 ...
- windows下curl报错:curl : (1) Protocol https not supported or disabled in libcurl
如果命令语句中有单引号,改为英文双引号试一下
- ./test.sh . ./test.sh source ./test.sh的区别
背景 今天写几个shell脚本,使用一个公共的config.sh,但是export出来的东西在另外的*.sh中不能直接用,这让我很惆怅,印象中就是可以export出来给别的shell用啊,只要不是下一 ...