Last active
August 2, 2021 02:51
-
-
Save starplatinum3/9b784ffdbbb61a5b11df434fda7e843f to your computer and use it in GitHub Desktop.
CustomerSpecifications jpa 封装的 字段相等和 时间之间方法 只要传入 有数据的对象 根据对象的值 和他一样的 才会被select ,还有时间在这个之间的 根据官方的代码 改的 我觉得可复用性比较高
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.springframework.data.domain.Page; | |
import org.springframework.data.domain.PageRequest; | |
import org.springframework.data.domain.Pageable; | |
import org.springframework.data.jpa.domain.Specification; | |
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | |
import java.time.LocalDate; | |
/** | |
* 比较通用的 根据传进来的 object 里面有的参数 不是null的话 就要去数据库了找和他一样的 | |
* 比如说 student name="吉良吉影" , age=33 就会找到 name="吉良吉影" , age=33 的人 | |
* 如果 student , age=33 就会找到 age=33 的人,这样的话 不就不用写 findByAge 这种东西了吗 | |
* 不过前端传参数需要 每次都传一个 student, 是不是比较浪费资源 反正我也不管了 | |
* 虽然说 findByAge 其实也只要声明一下就好了 | |
*/ | |
public class BaseRepository { | |
public static <T> Page<T> list(T object, Integer pageNumber, | |
Integer pageSize, | |
String fromDate, String toDate, | |
String dateStr, JpaSpecificationExecutor<T> repository) { | |
Specification<T> equal = CustomerSpecifications.equal(object); | |
LocalDate from = LocalDate.parse(fromDate); | |
LocalDate to = LocalDate.parse(toDate); | |
Specification<T> timeBetween = CustomerSpecifications.timeBetween(from, to, dateStr); | |
Pageable pageable = PageRequest.of(pageNumber, pageSize); | |
Page<T> all = repository.findAll(equal.and(timeBetween), pageable); | |
return all; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2011-2018 the original author or authors. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* https://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
//import example.springdata.jpa.showcase.core.Account; | |
//import example.springdata.jpa.showcase.core.Customer; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Modifier; | |
import java.lang.reflect.Type; | |
import java.time.LocalDate; | |
import java.util.*; | |
import javax.persistence.criteria.*; | |
import org.springframework.data.jpa.domain.Specification; | |
import org.springframework.data.repository.query.parser.PartTree; | |
/** | |
* Collection of {@link Specification} implementations. | |
* | |
* @author Oliver Gierke | |
*/ | |
public class CustomerSpecifications<T> { | |
/** | |
* byte Byte | |
* short Short | |
* int Integer | |
* long Long | |
* float Float | |
* double Double | |
* boolean Boolean | |
* char Character | |
* | |
* @param canonicalName | |
* @return | |
*/ | |
public static String primaryToPackaging(String canonicalName) { | |
switch (canonicalName) { | |
case "byte": | |
return "java.lang.Byte"; | |
case "short": | |
return "java.lang.Short"; | |
case "int": | |
return "java.lang.Integer"; | |
case "long": | |
return "java.lang.Long"; | |
case "float": | |
return "java.lang.Float"; | |
case "double": | |
return "java.lang.Double"; | |
case "boolean": | |
return "java.lang.Boolean"; | |
case "char": | |
return "java.lang.Character"; | |
default: | |
return canonicalName; | |
} | |
} | |
static Predicate[] removeNull(Predicate[] predicates) { | |
int cnt = 0; | |
for (Predicate predicate : predicates) { | |
if (predicate != null) | |
cnt++; | |
} | |
int j = 0; | |
Predicate[] predicatesNoNull = new Predicate[cnt]; | |
for (Predicate predicate : predicates) { | |
if (predicate != null) | |
predicatesNoNull[j++] = predicate; | |
} | |
return predicatesNoNull; | |
} | |
/** | |
* 从 from 到 to 时间的 记录 | |
* | |
* @param from | |
* @param to | |
* @param dateStr 根据 变量的名字 java 是驼峰(不一定,如果java 写的是 下划线就是下划线,就是根据java),而不是根据数据库 | |
* @param <T> | |
* @return | |
*/ | |
public static <T> Specification<T> timeBetween(LocalDate from, LocalDate to, String dateStr) { | |
// 姑且认为 root 不是从数据库查 而是定义要查的对象 | |
return (Specification<T>) (root, query, cb) -> { | |
// 这个query 应该没有连接数据库吧 其实是发起的 。 官方的例子 是从别的表里查一个 其实是做了join | |
// 这里如果自己的表 进行 query.from 的话,就会 cross join | |
// java.lang.IllegalArgumentException: Unable to locate Attribute | |
// with the the given name [send_date] on this ManagedType | |
Path<Date> date = root.<Date>get(dateStr); | |
// 需要这个嘛 根据 变量的名字 java 是驼峰 | |
// 根据entity里 定义的字段吗 | |
Predicate greaterThanOrEqualTo = cb.greaterThanOrEqualTo(date, java.sql.Date.valueOf(from)); | |
Predicate lessThanOrEqualTo = cb.lessThanOrEqualTo(date, java.sql.Date.valueOf(to)); | |
return cb.and(lessThanOrEqualTo, greaterThanOrEqualTo); | |
}; | |
} | |
public static <T> Specification<T> equal(Object object, List<String> excepts) { | |
return specificationByObj(object,excepts,Pattern.EQUAL); | |
} | |
enum Pattern{ | |
LIKE,EQUAL; | |
} | |
public static <T> Specification<T> specificationByObj(Object object, List<String> excepts,Pattern pattern) { | |
// 姑且认为 root 不是从数据库查 而是定义要查的对象 | |
return (Specification<T>) (root, query, cb) -> { | |
// 这个query 应该没有连接数据库吧 其实是发起的 。 官方的例子 是从别的表里查一个 其实是做了join | |
// 这里如果自己的表 进行 query.from 的话,就会 cross join | |
// 需要 类型 和 名字 | |
// 但是 类型是 数据库类型 应该 一样吧 | |
// 需要 type 和 字符串 | |
Field[] declaredFields = object.getClass().getDeclaredFields(); | |
Predicate[] predicates = new Predicate[declaredFields.length]; | |
int i = 0; | |
for (Field field : declaredFields) { | |
field.setAccessible(true); | |
String name = field.getName(); | |
if (name.equals("serialVersionUID")) { | |
continue; | |
} | |
if (excepts != null && excepts.contains(name)) { | |
continue; | |
} | |
Path<Object> objectPath = null; | |
try { | |
objectPath = root.get(name); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
try { | |
Object value = field.get(object); | |
if (!(value == null)) { | |
if(pattern==Pattern.EQUAL){ | |
predicates[i++] = cb.equal(objectPath, value); | |
}else if(pattern== Pattern.LIKE){ | |
predicates[i++] = cb.equal(objectPath, "%"+value+"%"); | |
} | |
} | |
// 不能有任何一个是 null | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
} | |
predicates = removeNull(predicates); | |
// 需要这个嘛 根据 变量的名字 java 是驼峰 | |
// 根据entity里 定义的字段吗 | |
return cb.and(predicates); | |
}; | |
} | |
public static <T> Specification<T> equal(Object object) { | |
return equal(object, null); | |
} | |
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { | |
Object redPacketRecord = new RedPacketRecord(); | |
Field[] declaredFields = redPacketRecord.getClass().getDeclaredFields(); | |
for (Field field : declaredFields) { | |
// System.out.println("field"); | |
// System.out.println(field); | |
System.out.println("accessible before"); | |
boolean accessible = field.isAccessible(); | |
System.out.println(accessible); | |
field.setAccessible(true); | |
System.out.println("获取到字段:" + field.getType().getCanonicalName() | |
+ ",值:" + field.get(redPacketRecord)); | |
String modifier = Modifier.toString(field.getModifiers()); | |
System.out.println(modifier); | |
// Object o = field.get(redPacketRecord); | |
// System.out.println("o"); | |
// System.out.println(o); | |
String name = field.getName(); | |
// System.out.println("name"); | |
//// 就要 name 是短的名字 | |
// System.out.println(name); | |
// | |
Type genericType = field.getGenericType(); | |
// System.out.println("genericType"); | |
// System.out.println(genericType); | |
// | |
// Class<?> aClass = Class.forName(String.valueOf(genericType).replace("class ","")); | |
// System.out.println("aClass"); | |
// System.out.println(aClass); | |
String genericString = field.toGenericString(); | |
// System.out.println("genericString"); | |
// System.out.println(genericString); | |
Class<?> type = field.getType(); | |
// System.out.println("type"); | |
// System.out.println(type); | |
// type | |
// class java.lang.Integer | |
// type | |
// long | |
// ListUtil.printListRet(Collections.singletonList(type)); | |
// ListUtil.printListRet(type); | |
Class<?> declaringClass = field.getDeclaringClass(); | |
// System.out.println("declaringClass"); | |
// System.out.println(declaringClass); | |
// declaringClass | |
Class<? extends Field> aClass = field.getClass(); | |
// System.out.println("aClass"); | |
// System.out.println(aClass); | |
// aClass | |
// class java.lang.reflect.Field | |
boolean accessibleAfter = field.isAccessible(); | |
System.out.println("accessibleAfter"); | |
System.out.println(accessibleAfter); | |
} | |
String simpleName = RedPacketRecord.class.getSimpleName(); | |
// System.out.println("simpleName"); | |
// System.out.println(simpleName); | |
// | |
Class<?>[] classes = RedPacketRecord.class.getClasses(); | |
// System.out.println("classes"); | |
// ListUtil.printListRet(Arrays.asList(classes)); | |
// RedPacketRecord.class | |
// Object redPacketRecord=new RedPacketRecord(); | |
// Field id = redPacketRecord.getClass().getField("redId"); | |
// | |
// | |
// System.out.println("id"); | |
// System.out.println(id); | |
// Object o = redPacketRecord.getClass().getField("redId").get("id"); | |
// System.out.println("o"); | |
// System.out.println(o); | |
// Object redPacketRecord2=new RedPacketRecord(); | |
// Field[] fields = redPacketRecord2.getClass().getDeclaredFields(); | |
// System.out.println("redPacketRecord2"); | |
// for (Field field : fields) { | |
// System.out.println(field.getName()); | |
// System.out.println(field.isAccessible()); | |
// } | |
// | |
// System.out.println("========"); | |
// fields = redPacketRecord.getClass().getFields(); | |
// 空的 | |
// 应该不是永久的 可以获得 那危险性应该不大 | |
// fields = redPacketRecord.getClass().getDeclaredFields(); | |
// System.out.println("redPacketRecord"); | |
// for (Field field : fields) { | |
// System.out.println(field.getName()); | |
// System.out.println(field.isAccessible()); | |
// } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//一个测试 | |
Page<Student> listPage = BaseRepository.list(student, | |
pageNumber, pageSize, fromDate, toDate, | |
"sendDate", studentRepository); | |
System.out.println("listPage"); | |
System.out.println(listPage); | |
System.out.println(listPage.getContent()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment