实现
PagingAndSortingRepository,
QueryDslPredicateExecutor,
JpaSpecificationExecutor
写了一个封装类,封装了查询通用条件
1、实现动态绑定entity任意属性去查询或者排序
2、也适用于update的话,只更新请求传过来的值去update,其他不变
3、动态构建PageRequest,实现多重排序条件
4、动态构建Specification, 实现多重条件查询
下面实例代码:
package base
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.querydsl.core.types.ExpressionUtils
import com.querydsl.core.types.Ops
import com.querydsl.core.types.Predicate
import com.querydsl.core.types.dsl.BooleanExpression
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.core.types.dsl.StringPath
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.data.jpa.domain.Specification
import org.springframework.web.bind.annotation.ExceptionHandler
import java.io.BufferedReader
import java.lang.reflect.Method
import java.util.ArrayList
import javax.persistence.criteria.CriteriaBuilder
import javax.persistence.criteria.CriteriaQuery
import javax.persistence.criteria.Root
/**
* Created by liushuhua on 25/03/2017.
*
* @ControllerAdvice will only kick in if an exception is thrown from within a controller method
*
**/
internal class EntityBuilder {
companion object Factory {
/**
* 构造query条件的Expression
* 将传递的参数自动绑定到Entity上
*
* @param Any
* @return BooleanExpression
*/
@ExceptionHandler(Throwable::class)
fun matchSelectiveAttrExpressions(obj: Any): BooleanExpression? {
val c = obj.javaClass
var rv: BooleanExpression? = null
val fs = c.getDeclaredFields()
for (i in fs.indices) {
val f = fs[i]
f.isAccessible = true //设置些属性是可以访问的
val `val` = f.get(obj)//得到此属性的值
if (`val` != null) {
val ce1 = Expressions.stringPath(lowerCaseClassName(c.getSimpleName()) + "." + f.name)
val ce2 = ExpressionUtils.toExpression(`val`)
val pred = Expressions.booleanOperation(Ops.EQ, ce1, ce2)
rv = if (rv != null) rv.and(pred) else pred
}
}
return rv
}
/**
* 构造update的Enity
* 将传递的参数绑定到该id的Entity上,
* 设置成新的Entity,id不变,再到数据库update
*
* @param Any1, Any2
* @return Any2
*/
@Throws(Exception::class)
fun matchSelectiveEntity(obj1: Any, obj2: Any): Any {
val fields = obj1.javaClass.declaredFields
// 遍历所有属性
for (j in fields.indices) {
val name = fields[j].name
if (fields[j].get(obj1) != null && !"createdAt".equals(name) && !"createdBy".equals(name)) {
val args = arrayOfNulls<Class<*>>(1)
args[0] = fields[j].type
val c = obj1.javaClass
val methodName = "set" + upperCaseClassName(name)
var method: Method? = null
method = c.getMethod(methodName, *args)
method!!.invoke(obj2, fields[j].get(obj1))
}
}
return obj2
}
/**
* 创建分页请求.
* pageNumber 从 1 开始
*/
@Throws(Exception::class)
fun buildPageRequest(jsonObject: JSONObject): PageRequest {
val pageNumber = Integer.parseInt(jsonObject["pageNumber"].toString())
val pagzSize = Integer.parseInt(jsonObject["pageSize"].toString())
val sortArray = jsonObject.getJSONArray("sort")
val sortList = ArrayList<Sort.Order>()
for (i in sortArray.indices) {
val ascFlag = sortArray.getJSONObject(i)["asc"].toString()
var order: Sort.Order? = null
if ("true" == ascFlag) {
order = Sort.Order(Sort.Direction.ASC, sortArray.getJSONObject(i)["field"].toString())
} else {
order = Sort.Order(Sort.Direction.DESC, sortArray.getJSONObject(i)["field"].toString())
}
sortList.add(order)
}
return PageRequest(pageNumber - 1, pagzSize, Sort(sortList))
}
/**
* 创建动态查询条件组合.
*/
@Throws(Exception::class)
fun <T> buildSpecification(jsonObject: JSONObject): Specification<T> {
val criteriaArray = jsonObject.getJSONArray("criteria")
val spec = Specification<T> { root, criteriaQuery, criteriaBuilder ->
val predicates = ArrayList<javax.persistence.criteria.Predicate>()
for (i in criteriaArray.indices) {
val field = criteriaArray.getJSONObject(i)["field"].toString()
val value = criteriaArray.getJSONObject(i)["value"].toString()
val operator = criteriaArray.getJSONObject(i)["operator"].toString()
if ("eq" == operator) {
predicates.add(criteriaBuilder.equal(root.get<Any>(field), value))
}
}
criteriaBuilder.and(*predicates.toTypedArray())
}
return spec
}
private fun lowerCaseClassName(name: String): String {
return name.substring(0, 1).toLowerCase() + name.substring(1)
}
private fun upperCaseClassName(name: String): String {
return name.substring(0, 1).toUpperCase() + name.substring(1)
}
}
}
调用查询方法
override fun listCustomer(jsonObject: JSONObject): MutableIterable<Customer> {
val pageable = EntityBuilder.buildPageRequest(jsonObject)
val spec = EntityBuilder.buildSpecification<Customer>(jsonObject)
return customerRepository.findAll(spec, pageable)
}
其中jsonObject是:
{
"pageNumber": "1",
"pageSize": "10",
"criteria": [{"operator": "like", "field": "name", "value": "aaa"}],
"sort": [{"field":"id","asc":"true"}]
}
调用更新方法
override fun save(customer: Customer) : Customer {
if(customer.id == null){
return customerRepository.save(customer)
}else{
val oldCustomer = findById(customer.id)
if(oldCustomer == null){
throw Exception("The entity not found")
}
val customer = EntityBuilder.matchSelectiveEntity(customer, oldCustomer!!) as Customer
return customerRepository.save(customer)
}
}