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 ...
随机推荐
- Access转Sqlite的最简单的方法(不需要DB Manager)
在网上查了很多方法,大部分都是需要DB Manager,但是DB Manager这个牛逼保护机制做得好,没有免费的注册码可用.还好下面有另一个办法实现Access转Sqlite: 首先要下载SQLit ...
- iOS 公司开发者账号申请清单
公司开发者账号申请清单: Apple ID账号申请: (有账号请提供账号密码) Apple ID: (最好是公司邮箱账号) Apple ID密码: (大于8位, 字母或数字组成, 包含 ...
- AppCompatActivity与toolbar的结合
原文:http://www.51itong.net/android-activity-appcompatactivity-toolbar-15750.html 另外一个博客:Android 5.x T ...
- 利用Impromptu实现duck typing的封装
Impromptu是一个动态生成代码实现接口的库,可以非常方便我们实现DuckType编程: public interface IUser { string Name { get; ...
- SSH 登录缓慢解决方案
SSH 登录太慢可能是 DNS 解析的问题,默认配置下 sshd 初次接受 ssh 客户端连接的时候会自动反向解析客户端 IP 以得到 ssh 客户端的域名或主机名. 如果这个时候 DNS 的反向解析 ...
- Android Studio打包:“APP_NAME" IS NOT TRANSLATED IN ZH, ZH_CN……..解决办法
开始用Android Studio更新到2.0稳定版,调试的时候没啥问题,在打包的时候出现了"app_name" is not translated in zh, zh_CN….. ...
- php图片木马讲解
这是一个非常有趣的后门,它并没有依靠正常模式去隐藏起内容(比如 base64/gzip 编码),但是它却把自己的数据隐藏在JPEG图片的EXIF头部中了.它也使用exif_read_data和preg ...
- PHP正则表达式之快速学习法
1.入门简介 简单的说,正则表达式是一种可以用于模式匹配和替换的强有力的工具.我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或 ...
- zStack学习笔记(原创,绝对不是抄的……)
我之前写的文章都没写上面那句,但是这篇写了,主要是因为zStack文章抄袭太严重……故此声明 因为涉及到数据的双向交互问题,所以在这里我考虑使用协议栈来实现数据的收发.首先说下如何在Zstack中添加 ...
- javaSE中的输入输出流---一个读取流,相应多个输出流。并且生成的碎片文件都有有序的编号
<span style="font-size:18px;">package com.io.other.split; import java.io.File; impor ...