一、定义一个查询条件容器

/**
* 定义一个查询条件容器
*
* @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动态查询封装的更多相关文章

  1. SSH动态查询封装接口介绍

    SSH动态查询封装接口介绍 1.查询记录总条数 public int count(Class c,Object[][] eq,Object[][] like,String[] group,String ...

  2. spring data jpa 动态查询(工具类封装)

    利用JPA的Specification<T>接口和元模型就实现动态查询了.但是这样每一个需要动态查询的地方都需要写一个这样类似的findByConditions方法,小型项目还好,大型项目 ...

  3. springboot整合spring data jpa 动态查询

    Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询,在实现动态查询时我们需要用到Criteria API,主要是以下三个: 1.Criteria ...

  4. spring jpa 动态查询(Specification)

    //dao层 继承 扩展仓库接口JpaSpecificationExecutor (JPA 2引入了一个标准的API)public interface CreditsEventDao extends ...

  5. Spring Data JPA动态查询(多条件and)

    entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerat ...

  6. spring JPA 动态查询

    没什么好说的,记住就行. 下面是在Service中的方法 Page<TStaff> staffs=dao.findAll(new Specification<TStaff>() ...

  7. Hibernate JPA 动态criteria语句针对null查询条件的特殊处理

    最近原Hibernate项目需要添加一个条件,结构有点类似下面的格式,学生和房间是多对一的关系,现在要查询所有没有房间的学生. Class Student{ @ManyToOne Room room; ...

  8. spring data jpa封装specification实现简单风格的动态查询

    github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...

  9. SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法

    软件152 尹以操 首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml ...

随机推荐

  1. Access转Sqlite的最简单的方法(不需要DB Manager)

    在网上查了很多方法,大部分都是需要DB Manager,但是DB Manager这个牛逼保护机制做得好,没有免费的注册码可用.还好下面有另一个办法实现Access转Sqlite: 首先要下载SQLit ...

  2. iOS 公司开发者账号申请清单

    公司开发者账号申请清单: Apple ID账号申请: (有账号请提供账号密码) Apple ID:       (最好是公司邮箱账号) Apple ID密码:  (大于8位, 字母或数字组成,  包含 ...

  3. AppCompatActivity与toolbar的结合

    原文:http://www.51itong.net/android-activity-appcompatactivity-toolbar-15750.html 另外一个博客:Android 5.x T ...

  4. 利用Impromptu实现duck typing的封装

    Impromptu是一个动态生成代码实现接口的库,可以非常方便我们实现DuckType编程: public interface IUser    {        string Name { get; ...

  5. SSH 登录缓慢解决方案

    SSH 登录太慢可能是 DNS 解析的问题,默认配置下 sshd 初次接受 ssh 客户端连接的时候会自动反向解析客户端 IP 以得到 ssh 客户端的域名或主机名. 如果这个时候 DNS 的反向解析 ...

  6. Android Studio打包:“APP_NAME" IS NOT TRANSLATED IN ZH, ZH_CN……..解决办法

    开始用Android Studio更新到2.0稳定版,调试的时候没啥问题,在打包的时候出现了"app_name" is not translated in zh, zh_CN….. ...

  7. php图片木马讲解

    这是一个非常有趣的后门,它并没有依靠正常模式去隐藏起内容(比如 base64/gzip 编码),但是它却把自己的数据隐藏在JPEG图片的EXIF头部中了.它也使用exif_read_data和preg ...

  8. PHP正则表达式之快速学习法

    1.入门简介 简单的说,正则表达式是一种可以用于模式匹配和替换的强有力的工具.我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或 ...

  9. zStack学习笔记(原创,绝对不是抄的……)

    我之前写的文章都没写上面那句,但是这篇写了,主要是因为zStack文章抄袭太严重……故此声明 因为涉及到数据的双向交互问题,所以在这里我考虑使用协议栈来实现数据的收发.首先说下如何在Zstack中添加 ...

  10. javaSE中的输入输出流---一个读取流,相应多个输出流。并且生成的碎片文件都有有序的编号

    <span style="font-size:18px;">package com.io.other.split; import java.io.File; impor ...