文档章节

springdata中Specification查询封装

SPPan
 SPPan
发布于 2017/05/31 15:24
字数 730
阅读 21
收藏 0
点赞 0
评论 0

1、定义操作符类:

package net.sppan.base.service.specification;
 
/**
 * 操作符类,这个类中存储了键值对和操作符号,另外存储了连接下一个条件的类型是and还是or
 * <br>
 * 创建时通过 id>=7,其中id就是key,>=就是oper操作符,7就是value
 * <br>
 * 特殊的自定义几个操作符(:表示like %v%,b:表示v%,:b表示%v)
 */
public class SpecificationOperator {
    /**
     * 操作符的key,如查询时的name,id之类
     */
    private String key;
    /**
     * 操作符的value,具体要查询的值
     */
    private Object value;
    /**
     * 操作符,自己定义的一组操作符,用来方便查询
     */
    private String oper;
    /**
     * 连接的方式:and或者or
     */
    private String join;
 
    public String getKey() {
        return key;
    }
 
    public void setKey(String key) {
        this.key = key;
    }
 
    public Object getValue() {
        return value;
    }
 
    public void setValue(Object value) {
        this.value = value;
    }
 
    public String getOper() {
        return oper;
    }
 
    public void setOper(String oper) {
        this.oper = oper;
    }
 
    public String getJoin() {
        return join;
    }
 
    public void setJoin(String join) {
        this.join = join;
    }
    
	public static enum Operator {
		eq, ge, le, gt, lt, likeL, likeR, likeAll, isNull, isNotNull, notEqual;
		@Override
		public String toString() {
			return name();
		}
	}
	public static enum Join {
		and, or;
		@Override
		public String toString() {
			return name();
		}
	}
}

2、Specification实现类:

package net.sppan.base.service.specification;
 
import net.sppan.base.service.specification.SpecificationOperator.Join;
 
import org.springframework.data.jpa.domain.Specification;
 
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
 
import java.util.List;
 
public class SimpleSpecification<T> implements Specification<T> {
 
    /**
     * 查询的条件列表,是一组列表
     * */
    private List<SpecificationOperator> opers;
 
    public SimpleSpecification(List<SpecificationOperator> opers) {
        this.opers = opers;
    }
 
    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        int index = 0;
        //通过resultPre来组合多个条件
        Predicate resultPre = null;
        for(SpecificationOperator op:opers) {
            if(index++==0) {
                resultPre = generatePredicate(root,criteriaBuilder,op);
                continue;
            }
            Predicate pre = generatePredicate(root,criteriaBuilder,op);
            if(pre==null) continue;
            if(Join.and.name().equalsIgnoreCase(op.getJoin())) {
                resultPre = criteriaBuilder.and(resultPre,pre);
            } else if(Join.or.name().equalsIgnoreCase(op.getJoin())) {
                resultPre = criteriaBuilder.or(resultPre,pre);
            }
        }
        return resultPre;
    }
 
    private Predicate generatePredicate(Root<T> root,CriteriaBuilder criteriaBuilder, SpecificationOperator op) {
        /*
        * 根据不同的操作符返回特定的查询*/
        if(SpecificationOperator.Operator.eq.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.equal(root.get(op.getKey()),op.getValue());
        } else if(SpecificationOperator.Operator.ge.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.ge(root.get(op.getKey()).as(Number.class), (Number)op.getValue());
        } else if(SpecificationOperator.Operator.le.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.le(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
        } else if(SpecificationOperator.Operator.gt.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.gt(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
        } else if(SpecificationOperator.Operator.lt.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.lt(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
        } else if(SpecificationOperator.Operator.likeAll.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.like(root.get(op.getKey()).as(String.class),"%"+op.getValue()+"%");
        } else if(SpecificationOperator.Operator.likeL.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.like(root.get(op.getKey()).as(String.class),op.getValue()+"%");
        } else if(SpecificationOperator.Operator.likeR.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.like(root.get(op.getKey()).as(String.class),"%"+op.getValue());
        } else if(SpecificationOperator.Operator.isNull.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.isNull(root.get(op.getKey()));
        } else if(SpecificationOperator.Operator.isNotNull.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.isNotNull(root.get(op.getKey()));
        } else if(SpecificationOperator.Operator.notEqual.name().equalsIgnoreCase(op.getOper())) {
            return criteriaBuilder.notEqual(root.get(op.getKey()),op.getValue());
        }
        return null;
    }
 
}

3、查询条件构造类:

package net.sppan.base.service.specification;
 
import java.util.ArrayList;
import java.util.List;
 
import net.sppan.base.service.specification.SpecificationOperator.Join;
 
import org.springframework.data.jpa.domain.Specification;
 
public class SimpleSpecificationBuilder<T> {
 
    /**
     * 条件列表
     */
    private List<SpecificationOperator> opers;
 
    /**
     * 构造函数,初始化的条件是and
     */
    public SimpleSpecificationBuilder(String key,String oper,Object value) {
        SpecificationOperator so = new SpecificationOperator();
        so.setJoin(Join.and.name());
        so.setKey(key);
        so.setOper(oper);
        so.setValue(value);
        opers = new ArrayList<SpecificationOperator>();
        opers.add(so);
    }
 
    public SimpleSpecificationBuilder() {
        opers = new ArrayList<SpecificationOperator>();
    }
 
    /**
     * 完成条件的添加
     * @return
     */
    public SimpleSpecificationBuilder<T> add(String key,String oper,Object value,String join) {
        SpecificationOperator so = new SpecificationOperator();
        so.setKey(key);
        so.setValue(value);
        so.setOper(oper);
        so.setJoin(join);
        opers.add(so);
        return this;
    }
 
 
    /**
     * 添加or条件的重载
     * @return this,方便后续的链式调用
     */
    public SimpleSpecificationBuilder<T> addOr(String key,String oper,Object value) {
        return this.add(key,oper,value,Join.or.name());
    }
 
    /**
     * 添加and的条件
     * @return
     */
    public SimpleSpecificationBuilder<T> add(String key,String oper,Object value) {
        return this.add(key,oper,value,Join.and.name());
    }
 
 
    public Specification<T> generateSpecification() {
        Specification<T> specification = new SimpleSpecification<T>(opers);
        return specification;
    }
}

4、使用示例

SimpleSpecificationBuilder<Resource> builder = new SimpleSpecificationBuilder<Resource>();//Resource 持久层实体
builder.add("name", Operator.likeAll.name(), "keyword");
Specification specification = builder.generateSpecification()

© 著作权归作者所有

共有 人打赏支持
SPPan
粉丝 10
博文 29
码字总数 15103
作品 0
成都
程序员
Spring Data Redis与Jedis的选择(转)

说明:内容可能有点旧,需要在业务上做权衡。 Redis的客户端有两种实现方式,一是可以直接调用Jedis来实现,二是可以使用Spring Data Redis,通过Spring的封装来调用。应该使用哪一个呢?基于...

easonjim ⋅ 2017/11/08 ⋅ 0

spring data mongo如何查询给定多边形内所有坐标点?

使用spring data mongodb 如何查询给定多边形内所有坐标点?能否给个使用示例看看?

K哥 ⋅ 04/12 ⋅ 0

Spring集成Redis方案(spring-data-redis)(基于Jedis的单机模式)(待实践)

说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点。并且会与一些低版本的Spring有冲突,要看官方文档...

easonjim ⋅ 2017/10/05 ⋅ 0

Java for Web学习笔记(一二一):搜索(3)JPA的动态条件搜索(下)

例子的具体实现 仓库的实现 使用spring data,增加自定义接口SearchableRepository,具体如下: public interface PersonRepository extends CrudRepository, SearchableRepository{} publi......

flowingflying ⋅ 04/15 ⋅ 0

Springboot JPA 表实体关联自身的问题

部门表是有上下级关系的,建立如下: CREATE TABLE ( bigint(20) NOT NULL AUTOINCREMENT, `deptpiddeptnamedeptcodedeptdescdeptid`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAU......

nhks ⋅ 04/19 ⋅ 0

使用Spring Data Redis操作Redis(单机版)

说明:请注意Spring Data Redis的版本以及Spring的版本!最新版本的Spring Data Redis已经去除Jedis的依赖包,需要自行引入,这个是个坑点。并且会与一些低版本的Spring有冲突,要看官方文档...

easonjim ⋅ 2017/11/08 ⋅ 0

Spring Boot使用Spring Data Redis操作Redis(单机/集群)

说明:Spring Boot简化了Spring Data Redis的引入,只要引入spring-boot-starter-data-redis之后会自动下载相应的Spring Data Redis和Jedis客户端,可以减少版本这块的冲突,当然,如果要引入...

easonjim ⋅ 2017/11/08 ⋅ 0

第二章——Spring Boot启动器与依赖管理

强烈推荐选择支持依赖管理和可以发布到“Maven中央”仓库的构建系统。推荐使用Maven或Gradle。Spring Boot可以使用其他构建系统(例如,Ant),但支持得并不是很好。 1 依赖管理 Spring Boo...

Leech ⋅ 02/04 ⋅ 0

Spring Data Elasticsearch 和 x-pack 用户名/密码验证连接

使用Spring Data Elasticsearch连接elasticsearch时,正常情况下只需要在application.properites文件中添加如下配置即可连接: 以看到Spring Data Elasticsearch连接elasticsearch很简单。 ...

kipeng300 ⋅ 04/24 ⋅ 0

whoismy8023/SPPanAdmin

系统管理后台基本框架SPPanAdmin,包括用户管理,角色管理,资源链接管理模块,可以动态分配权限和角色。 使用springboot、springdata jpa、shiro等服务端技术,使用freemarker模版渲染页面。...

whoismy8023 ⋅ 2017/01/20 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

在java中读取文件(也支持读取jar中的文件)

getClass().getResourceAsStream("文件名.格式"); 这个方法是用于获取当前类所在目录下的文件;需要将文件放到和当前类同一个包下面 比如我有个类在 com.test这个包下, 要读取一个test.jpg的图...

太黑_thj ⋅ 51分钟前 ⋅ 0

CentOS 7 源码编译安装 MySQL 5.7记录

没事瞎折腾,本来可以yum安装,却偏偏去要编译源码。 1. 安装依赖包 1). 安装cmake等依赖 # yum install cmake ncurses ncurses-devel bison bison-devel 2). 安装boost 1.59.0 # wget htt...

admin_qing ⋅ 53分钟前 ⋅ 0

tcp/ip详解-链路层

简介 设计链路层的目的: 为IP模块发送和接收IP数据报 为ARP模块发送ARP请求和接收ARP应答 为RARP模块发送RARP请求和接收RARP应答 TCP/IP支持多种链路层协议,如以太网、令牌环往、FDDI、RS-...

loda0128 ⋅ 今天 ⋅ 0

spring.net aop代码例子

https://www.cnblogs.com/haogj/archive/2011/10/12/2207916.html

whoisliang ⋅ 今天 ⋅ 0

发送短信如何限制1小时内最多发送11条短信

发送短信如何限制1小时内最多发送11条短信 场景: 发送短信属于付费业务,有时为了防止短信攻击,需要限制发送短信的频率,例如在1个小时之内最多发送11条短信. 如何实现呢? 思路有两个 截至到当...

黄威 ⋅ 昨天 ⋅ 0

mysql5.7系列修改root默认密码

操作系统为centos7 64 1、修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不对密码进行验证 2、重启 mysqld 服务:systemctl restart mysql...

sskill ⋅ 昨天 ⋅ 0

Intellij IDEA神器常用技巧六-Debug详解

在调试代码的时候,你的项目得debug模式启动,也就是点那个绿色的甲虫启动服务器,然后,就可以在代码里面断点调试啦。下面不要在意,这个快捷键具体是啥,因为,这个keymap是可以自己配置的...

Mkeeper ⋅ 昨天 ⋅ 0

zip压缩工具、tar打包、打包并压缩

zip 支持压缩目录 1.在/tmp/目录下创建目录(study_zip)及文件 root@yolks1 study_zip]# !treetree 11└── 2 └── 3 └── test_zip.txt2 directories, 1 file 2.yum...

蛋黄Yolks ⋅ 昨天 ⋅ 0

聊聊HystrixThreadPool

序 本文主要研究一下HystrixThreadPool HystrixThreadPool hystrix-core-1.5.12-sources.jar!/com/netflix/hystrix/HystrixThreadPool.java /** * ThreadPool used to executed {@link Hys......

go4it ⋅ 昨天 ⋅ 0

容器之上传镜像到Docker hub

Docker hub在国内可以访问,首先要创建一个账号,这个后面会用到,我是用126邮箱注册的。 1. docker login List-1 Username不能使用你注册的邮箱,要用使用注册时用的username;要输入密码 ...

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部