使用JPA支持多參數(shù)列表查詢(參數(shù)可能為空)
JPA支持多參數(shù)列表查詢(參數(shù)可能為空)
1.JPA 支持寫SQL語句查詢
@Query(value = "select * from xxx ",nativeQuery = true)
2.JPA @Query的SQL語句
可以通過?1、?2
這樣獲取查詢方法里第一個(gè)參數(shù)、第二個(gè)參數(shù),以此類推;或者是使用@Param("name")
標(biāo)識(shí)參數(shù),然后使用 :name
獲取。
3.mysql 的if函數(shù),類似三目運(yùn)算
if(sex=1, '男' , '女')
結(jié)合起來可以使用MySQL的if函數(shù),來判斷參數(shù)是否為空,為空時(shí)設(shè)置1=1,也就是查所有。
- 第一種方式:
?1
獲取參數(shù)
@Query(value = "select * from test_demo where if(?1 !='',name=?1,1=1) and if(?2 !='',info=?2,1=1) ",nativeQuery = true) List<TestDemo> find(String name, String info) ;
- 第二種方式:
:name
獲取參數(shù)
@Query(value = "select * from test_demo where if(:name !='',name= :name,1=1) and if(:info !='',info= :info,1=1) ",nativeQuery = true) List<TestDemo> find2(@Param("name") String name, @Param("info") String info) ;
- 第三種方式:實(shí)體類獲取參數(shù)
@Query(value = "select * from test_demo where if(:#{#testDemo.name} !='',name=:#{#testDemo.name},1=1) and if(:#{#testDemo.info} !='',info=:#{#testDemo.info},1=1) ",nativeQuery = true) List<TestDemo> find3(@Param("testDemo")TestDemo testDemo) ;
這三種寫法結(jié)果是一樣的,主要邏輯就是使用MySQL的if函數(shù),判斷某個(gè)字段是否不為空,是的話就根據(jù)這個(gè)字段查詢,否則就1=1(為了保證sql語句可以執(zhí)行)。
同理可以拓展很多,包括模糊查詢等,只要MySQL 支持的SQL語句就可以使用JPA來實(shí)現(xiàn),同時(shí)JPA特有的分頁也可以實(shí)現(xiàn)只需要傳遞Pageable對象并使用Page 接收數(shù)據(jù)即可。
@Query(value = "select * from test_demo where if(?1 !='',name=?1,1=1) and if(?2 !='',info=?2,1=1) ",nativeQuery = true) Page<TestDemo> find(String name, String info, Pageable pageable) ;
JPA動(dòng)態(tài)查詢 支持多字段模糊查詢 排序
1、定義條件容器
import org.springframework.data.jpa.domain.Specification; import org.springframework.util.CollectionUtils; import javax.persistence.criteria.*; import java.util.ArrayList; import java.util.List; /** * 定義一個(gè)查詢條件容器 * Created by gzs */ public class Criteria<T> implements Specification<T> { private List<Criterion> criterions = new ArrayList<>(); private List<Criterion> orderCriterions = new ArrayList<>(); private List<Criterion> groupCriterions = new ArrayList<>(); @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { //處理查詢條件 if (!criterions.isEmpty()) { List<Predicate> predicates = new ArrayList<>(); for (Criterion c : criterions) { Predicate predicate = c.toPredicate(root, query, builder); predicates.add(predicate); } // 將所有條件用 and 聯(lián)合起來 if (predicates.size() > 0) { query.where(predicates.toArray(new Predicate[predicates.size()])); } // 將所有條件用 and 聯(lián)合起來 /*if (predicates.size() > 0) { return builder.and(predicates.toArray(new Predicate[predicates.size()])); }*/ } //處理排序 if (!orderCriterions.isEmpty()) { List<Order> orders = new ArrayList<>(); for (Criterion c : orderCriterions) { Order order = c.toOrder(root, query, builder); orders.add(order); } if (!CollectionUtils.isEmpty(orders)) { query.orderBy(orders); } } //處理分組 if (!groupCriterions.isEmpty()) { List<Expression> groups = new ArrayList<>(); for (Criterion c : groupCriterions) { Expression group = c.toGroupBy(root, query, builder); groups.add(group); } if (!CollectionUtils.isEmpty(groups)) { Expression[] groupExpressions = (Expression[]) groups.toArray(); query.groupBy(groupExpressions); } } return query.getRestriction(); //return builder.conjunction(); } /** * 增加簡單條件表達(dá)式 * * @Methods Name add * @Create In 2018-10-15 By gzs */ public void add(Criterion criterion) { if (criterion != null) { criterions.add(criterion); } } /** * 增加排序表達(dá)式 * * @Methods Name add * @Create In 2018-11-15 By gzs */ public void addOrder(Criterion order) { if (order != null) { orderCriterions.add(order); } } /** * 增加排序表達(dá)式 * * @Methods Name add * @Create In 2018-11-15 By gzs */ public void addGroupBy(Criterion group) { if (group != null) { groupCriterions.add(group); } } }
2、條件表達(dá)式
import javax.persistence.criteria.*; /** * 創(chuàng)建條件表達(dá)式接口,模擬系統(tǒng)的條件查詢 * Created by gzs */ public interface Criterion { enum Operator { EQ, NE, LIKE, GT, LT, GTE, LTE, IS_NULL, IS_NOT_NULL, AND, OR, IS_MEMBER, IS_NOT_MEMBER, DESC, ASC } Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); Expression toGroupBy(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); }
3、實(shí)現(xiàn)邏輯條件表達(dá)式
import javax.persistence.criteria.*; import java.util.ArrayList; import java.util.List; /** * 邏輯條件表達(dá)式 用于復(fù)雜條件時(shí)使用,如單屬性多對應(yīng)值的OR查詢等 * * Created by gzs */ public class LogicalExpression implements Criterion { /** * 邏輯表達(dá)式中包含的表達(dá)式 */ private Criterion[] criterion; /** * 計(jì)算符 */ private Operator operator; public LogicalExpression(Criterion[] criterions, Operator operator) { this.criterion = criterions; this.operator = operator; } @Override public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { List<Predicate> predicates = new ArrayList<>(); for (int i = 0; i < this.criterion.length; i++) { Predicate predicate = this.criterion[i].toPredicate(root, query, builder); predicates.add(predicate); } 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; } } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Expression toGroupBy(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } }
4、實(shí)現(xiàn)簡單條件表達(dá)式
import org.springframework.util.StringUtils; import javax.persistence.criteria.*; import java.util.List; import java.util.Map; import java.util.Set; /** * 簡單條件表達(dá)式 * * Created by gzs */ public class SimpleExpression implements Criterion { /** * 屬性名 */ private String fieldName; /** * 對應(yīng)值 */ private Object value; /** * 計(jì)算符 */ private Operator operator; protected SimpleExpression(String fieldName, Operator operator) { this.fieldName = fieldName; this.operator = operator; } protected SimpleExpression(String fieldName, Object value, Operator operator) { this.fieldName = fieldName; this.value = value; this.operator = operator; } @Override @SuppressWarnings({"rawtypes", "unchecked"}) public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression; //此處是表關(guān)聯(lián)數(shù)據(jù),注意僅限一層關(guān)聯(lián),如user.address, //查詢user的address集合中,address的name為某個(gè)值 if (fieldName.contains(".")) { String[] names = StringUtils.split(fieldName, "."); //獲取該屬性的類型,Set?List?Map? expression = root.get(names[0]); Class clazz = expression.getJavaType(); if (clazz.equals(Set.class)) { SetJoin setJoin = root.joinSet(names[0]); expression = setJoin.get(names[1]); } else if (clazz.equals(List.class)) { ListJoin listJoin = root.joinList(names[0]); expression = listJoin.get(names[1]); } else if (clazz.equals(Map.class)) { MapJoin mapJoin = root.joinMap(names[0]); expression = mapJoin.get(names[1]); } else { //是many to one時(shí) expression = expression.get(names[1]); } } 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); case IS_NULL: return builder.isNull(expression); case IS_NOT_NULL: return builder.isNotNull(expression); case IS_MEMBER: return builder.isMember(value, expression); case IS_NOT_MEMBER: return builder.isNotMember(value, expression); default: return null; } } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Expression toGroupBy(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } }
5、實(shí)現(xiàn)排序表達(dá)式
import org.springframework.util.StringUtils; import javax.persistence.criteria.*; import java.util.List; import java.util.Map; import java.util.Set; /** * 邏輯條件表達(dá)式 用于復(fù)雜條件時(shí)使用,如單屬性多對應(yīng)值的OR查詢等 * * Created by gzs */ public class OrderExpression implements Criterion { /** * 計(jì)算符 */ private Operator operator; /** * 屬性名 */ private String fieldName; public OrderExpression(String fieldName, Operator operator) { this.fieldName = fieldName; this.operator = operator; } @Override public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression; //此處是表關(guān)聯(lián)數(shù)據(jù),注意僅限一層關(guān)聯(lián),如user.address, //查詢user的address集合中,address的name為某個(gè)值 if (fieldName.contains(".")) { String[] names = StringUtils.split(fieldName, "."); //獲取該屬性的類型,Set?List?Map? expression = root.get(names[0]); Class clazz = expression.getJavaType(); if (clazz.equals(Set.class)) { SetJoin setJoin = root.joinSet(names[0]); expression = setJoin.get(names[1]); } else if (clazz.equals(List.class)) { ListJoin listJoin = root.joinList(names[0]); expression = listJoin.get(names[1]); } else if (clazz.equals(Map.class)) { MapJoin mapJoin = root.joinMap(names[0]); expression = mapJoin.get(names[1]); } else { //是many to one時(shí) expression = expression.get(names[1]); } } else { //單表查詢 expression = root.get(fieldName); } switch (operator) { case DESC: return builder.desc(expression); default: return builder.asc(expression); } } @Override public Expression toGroupBy(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } }
6、實(shí)現(xiàn)分組表達(dá)式 GroupByExpression
import org.springframework.util.StringUtils; import javax.persistence.criteria.*; import java.util.List; import java.util.Map; import java.util.Set; /** * 分組條件表達(dá)式 用于復(fù)雜條件時(shí)使用等 * * Created by gzs */ public class GroupByExpression implements Criterion { /** * 屬性名 */ private String fieldName; public GroupByExpression(String fieldName) { this.fieldName = fieldName; } @Override public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Expression toGroupBy(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression; //此處是表關(guān)聯(lián)數(shù)據(jù),注意僅限一層關(guān)聯(lián),如user.address, //查詢user的address集合中,address的name為某個(gè)值 if (fieldName.contains(".")) { String[] names = StringUtils.split(fieldName, "."); //獲取該屬性的類型,Set?List?Map? expression = root.get(names[0]); Class clazz = expression.getJavaType(); if (clazz.equals(Set.class)) { SetJoin setJoin = root.joinSet(names[0]); expression = setJoin.get(names[1]); } else if (clazz.equals(List.class)) { ListJoin listJoin = root.joinList(names[0]); expression = listJoin.get(names[1]); } else if (clazz.equals(Map.class)) { MapJoin mapJoin = root.joinMap(names[0]); expression = mapJoin.get(names[1]); } else { //是many to one時(shí) expression = expression.get(names[1]); } } else { //單表查詢 expression = root.get(fieldName); } return expression; } }
import org.springframework.util.StringUtils; import java.util.Collection; /** * 條件構(gòu)造器 * 用于創(chuàng)建條件表達(dá)式 * * Created by gzs */ public class Restrictions { /** * 等于 */ public static SimpleExpression eq(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.EQ); } /** * 為null */ public static SimpleExpression isNull(String fieldName) { return new SimpleExpression(fieldName, Criterion.Operator.IS_NULL); } /** * 不為null */ public static SimpleExpression isNotNull(String fieldName) { return new SimpleExpression(fieldName, Criterion.Operator.IS_NOT_NULL); } /** * 集合包含某個(gè)元素 */ public static SimpleExpression hasMember(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.IS_MEMBER); } /** * 不等于 */ public static SimpleExpression ne(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.NE); } /** * 模糊匹配 */ public static SimpleExpression like(String fieldName, String value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LIKE); } /** */ // public static SimpleExpression like(String fieldName, String value, // MatchMode matchMode, boolean ignoreNull) { // if (StringUtils.isEmpty(value)) return null; // return null; // } /** * 大于 */ public static SimpleExpression gt(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.GT); } /** * 小于 */ public static SimpleExpression lt(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LT); } /** * 小于等于 */ public static SimpleExpression lte(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LTE); } /** * 大于等于 */ public static SimpleExpression gte(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.GTE); } /** * 降序 */ public static OrderExpression desc(String fieldName) { /*if (StringUtils.isEmpty(fieldName)) { return null; }*/ return new OrderExpression(fieldName, Criterion.Operator.DESC); } /** * 升序 */ public static OrderExpression asc(String fieldName) { /*if (StringUtils.isEmpty(fieldName)) { return null; }*/ return new OrderExpression(fieldName, Criterion.Operator.ASC); } /** * 并且 */ public static LogicalExpression and(Criterion... criterions) { return new LogicalExpression(criterions, Criterion.Operator.AND); } /** * 或者 */ public static LogicalExpression or(Criterion... criterions) { return new LogicalExpression(criterions, Criterion.Operator.OR); } /** * 包含于 */ @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); } /** * 集合包含某幾個(gè)元素,譬如可以查詢User類中Set<String> set包含"ABC","bcd"的User集合, * 或者查詢User中Set<Address>的Address的name為"北京"的所有User集合 * 集合可以為基本類型或者JavaBean,可以是one to many或者是@ElementCollection * @param fieldName * 列名 * @param value * 集合 * @return * expresssion */ public static LogicalExpression hasMembers(String fieldName, Object... value) { SimpleExpression[] ses = new SimpleExpression[value.length]; int i = 0; //集合中對象是基本類型,如Set<Long>,List<String> Criterion.Operator operator = Criterion.Operator.IS_MEMBER; //集合中對象是JavaBean if (fieldName.contains(".")) { operator = Criterion.Operator.EQ; } for (Object obj : value) { ses[i] = new SimpleExpression(fieldName, obj, operator); i++; } return new LogicalExpression(ses, Criterion.Operator.OR); } /** * 分組 */ public static GroupByExpression groupBy(String fieldName) { if (StringUtils.isEmpty(fieldName)) { return null; } return new GroupByExpression(fieldName); } }
7、見證奇跡的時(shí)刻來了demo
if (StringUtils.isNotBlank(teacher.getContactName())) { //動(dòng)態(tài)查詢 Criteria<Teacher> criteria = new Criteria<>(); final LogicalExpression or = Restrictions.or( Restrictions.like("code", teacher.getContactName(), true), Restrictions.like("contactName", teacher.getContactName(), true), Restrictions.like("mobile", teacher.getContactName(), true)); criteria.add(or); criteria.add(Restrictions.eq("groupMerchantId", teacher.getGroupMerchantId(), true)); criteria.add(Restrictions.eq("merchantId", teacher.getMerchantId(), true)); criteria.add(Restrictions.eq("campusId", teacher.getCampusId(), true)); criteria.addOrder(Restrictions.desc("gmtModified")); Pageable pageable = new PageRequest(pageNo - 1, pageSize); //頁碼:前端從1開始,jpa從0開始,做個(gè)轉(zhuǎn)換 org.springframework.data.domain.Page<Teacher> cmsUsers = teacherRepository.findAll(criteria, pageable);
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決SpringBoot整合ElasticSearch遇到的連接問題
這篇文章主要介紹了解決SpringBoot整合ElasticSearch遇到的連接問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08java網(wǎng)絡(luò)爬蟲連接超時(shí)解決實(shí)例代碼
這篇文章主要介紹了java網(wǎng)絡(luò)爬蟲連接超時(shí)解決的問題,分享了一則使用httpclient解決連接超時(shí)的Java爬蟲實(shí)例代碼,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Java中實(shí)現(xiàn)文件預(yù)覽的功能(實(shí)例代碼)
大家都知道word,Excel,PPT實(shí)現(xiàn)在線預(yù)覽常用的方式就是先轉(zhuǎn)換成pdf,然后在進(jìn)行預(yù)覽,下面給大家介紹Java中如何實(shí)現(xiàn)文件預(yù)覽的功能,需要的朋友可以參考下2023-05-05Spring?Boot超大文件上傳實(shí)現(xiàn)秒傳功能
這篇文章主要介紹了Spring?Boot超大文件上傳實(shí)現(xiàn)秒傳功能,在實(shí)現(xiàn)分片上傳的過程,需要前端和后端配合,比如前后端的上傳塊號(hào)的文件大小,前后端必須得要一致,否則上傳就會(huì)有問題,需要的朋友可以參考下2022-12-12