重构query,拆分功能

This commit is contained in:
2020-05-19 00:08:02 +08:00
parent ddd4470b85
commit f9b3424899
30 changed files with 232 additions and 338 deletions

View File

@@ -5,7 +5,7 @@ dependencies {
publishing {
publications {
mavenJava(MavenPublication) {
publish(MavenPublication) {
group 'com.synebula'
artifactId 'gaea.mongo'
version "$version"

View File

@@ -0,0 +1,60 @@
package com.synebula.gaea.mongo
import com.synebula.gaea.query.OrderType
import org.springframework.data.domain.Sort
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
import java.lang.reflect.Field
/**
* 获取查询条件
*
* @param fields 字段列表
*/
fun Query.select(fields: Array<String>): Query {
fields.forEach {
this.fields().include(it)
}
return this
}
/**
* 根据参数获取查询条件
*
* @param params 参数列表
*/
fun Query.where(params: Map<String, Any>?): Query {
val criteria = Criteria()
if (params != null) {
for (param in params) {
criteria.and(param.key).isEqualTo(param.value)
}
}
return this.addCriteria(criteria)
}
/**
* 获取ID查询条件
*
* @param id 业务ID
*/
fun <TKey> whereId(id: TKey): Query = Query(Criteria("_id").isEqualTo(id))
/**
* 获取排序对象
*
* @param orders 排序条件字段
*/
fun order(orders: Map<String, OrderType>?): Sort {
val orderList = mutableListOf<Sort.Order>()
orders?.forEach {
orderList.add(Sort.Order(Sort.Direction.valueOf(it.value.name), it.key))
}
return if (orderList.size == 0)
Sort.by("_id")
else
Sort.by(orderList)
}

View File

@@ -1,7 +1,12 @@
package com.synebula.gaea.query.mongo
package com.synebula.gaea.mongo.query
import com.synebula.gaea.extension.fields
import com.synebula.gaea.extension.firstCharLowerCase
import com.synebula.gaea.log.ILogger
import com.synebula.gaea.mongo.order
import com.synebula.gaea.mongo.select
import com.synebula.gaea.mongo.where
import com.synebula.gaea.mongo.whereId
import com.synebula.gaea.query.IQuery
import com.synebula.gaea.query.PagingData
import com.synebula.gaea.query.PagingParam
@@ -12,8 +17,7 @@ import org.springframework.data.mongodb.core.query.Query
* 实现IQuery的Mongo查询类
* @param repo MongoRepo对象
*/
open class MongoQuery<TView>(var repo: MongoTemplate, override var logger: ILogger? = null) :
IQuery<TView, String>, IMongoQuery {
open class MongoQuery<TView>(var repo: MongoTemplate, var logger: ILogger? = null) : IQuery<TView, String> {
/**
* 查询的对象类
*/
@@ -74,10 +78,10 @@ open class MongoQuery<TView>(var repo: MongoTemplate, override var logger: ILogg
override fun list(params: Map<String, Any>?): List<TView> {
this.check()
return if (this.clazz != null) {
val viewFields = this.fields(this.clazz!!)
val fields = this.clazz!!.fields()
val query = Query()
this.where(query, params, this.clazz!!)
this.select(query, viewFields.toTypedArray())
query.select(fields.toTypedArray())
query.where(params)
this.repo.find(query, this.clazz!!, this.collection)
} else listOf()
}
@@ -86,21 +90,19 @@ open class MongoQuery<TView>(var repo: MongoTemplate, override var logger: ILogg
this.check()
return if (this.clazz != null) {
val query = Query()
this.repo.count(where(query, params, this.clazz!!), this.collection).toInt()
this.repo.count(query.where(params), this.collection).toInt()
} else 0
}
override fun paging(params: PagingParam): PagingData<TView> {
this.check()
return if (this.clazz != null) {
val viewFields = this.fields(this.clazz!!)
val result = PagingData<TView>(1, 10)
result.size = params.size
result.page = params.page
val query = Query()
this.where(query, params.parameters, this.clazz!!)
result.total = this.repo.count(query, this.collection).toInt()
this.select(query, viewFields.toTypedArray())
val fields = this.clazz!!.fields()
val result = PagingData<TView>(params.page, params.size)
query.where(params.parameters)
result.total = this.count(params.parameters)
query.select(fields.toTypedArray())
query.with(order(params.orderBy))
query.skip(params.index).limit(params.size)
result.data = this.repo.find(query, this.clazz!!, this.collection)
@@ -111,7 +113,7 @@ open class MongoQuery<TView>(var repo: MongoTemplate, override var logger: ILogg
override fun get(key: String): TView? {
this.check()
return if (this.clazz != null) {
val view = this.repo.findOne(idQuery(key), this.clazz!!, this.collection)
val view = this.repo.findOne(whereId(key), this.clazz!!, this.collection)
view
} else null
}

View File

@@ -1,7 +1,12 @@
package com.synebula.gaea.query.mongo
package com.synebula.gaea.mongo.query
import com.synebula.gaea.extension.fields
import com.synebula.gaea.extension.firstCharLowerCase
import com.synebula.gaea.log.ILogger
import com.synebula.gaea.mongo.order
import com.synebula.gaea.mongo.select
import com.synebula.gaea.mongo.where
import com.synebula.gaea.mongo.whereId
import com.synebula.gaea.query.IQueryTyped
import com.synebula.gaea.query.PagingData
import com.synebula.gaea.query.PagingParam
@@ -14,7 +19,7 @@ import java.lang.RuntimeException
* @param repo MongoRepo对象
*/
open class MongoQueryTyped(var repo: MongoTemplate, override var logger: ILogger? = null) : IQueryTyped, IMongoQuery {
open class MongoQueryTyped(var repo: MongoTemplate, var logger: ILogger? = null) : IQueryTyped {
/**
* 查询的集合名称
@@ -29,28 +34,28 @@ open class MongoQueryTyped(var repo: MongoTemplate, override var logger: ILogger
*/
var validViewCollection = false
override fun <TView, TKey> list(params: Map<String, Any>?, clazz: Class<TView>): List<TView> {
val viewFields = this.fields(clazz)
override fun <TView> list(params: Map<String, Any>?, clazz: Class<TView>): List<TView> {
val fields = clazz.fields()
val query = Query()
this.where(query, params, clazz)
this.select(query, viewFields.toTypedArray())
query.where(params)
query.select(fields.toTypedArray())
return this.repo.find(query, clazz, this.collection(clazz))
}
override fun <TView, TKey> count(params: Map<String, Any>?, clazz: Class<TView>): Int {
override fun <TView> count(params: Map<String, Any>?, clazz: Class<TView>): Int {
val query = Query()
return this.repo.count(this.where(query, params, clazz), this.collection(clazz)).toInt()
return this.repo.count(query.where(params), this.collection(clazz)).toInt()
}
override fun <TView, TKey> paging(params: PagingParam, clazz: Class<TView>): PagingData<TView> {
val viewFields = this.fields(clazz)
override fun <TView> paging(params: PagingParam, clazz: Class<TView>): PagingData<TView> {
val fields = clazz.fields()
val result = PagingData<TView>(1, 10)
result.size = params.size
result.page = params.page
val query = Query()
this.where(query, params.parameters, clazz)
result.total = this.count<TView, TKey>(params.parameters, clazz)
this.select(query, viewFields.toTypedArray())
query.where(params.parameters)
result.total = this.count(params.parameters, clazz)
query.select(fields.toTypedArray())
query.with(order(params.orderBy))
query.skip(params.index).limit(params.size)
result.data = this.repo.find(query, clazz, this.collection(clazz))
@@ -58,7 +63,7 @@ open class MongoQueryTyped(var repo: MongoTemplate, override var logger: ILogger
}
override fun <TView, TKey> get(key: TKey, clazz: Class<TView>): TView? {
return this.repo.findOne(idQuery(key), clazz, this.collection(clazz))
return this.repo.findOne(whereId(key), clazz, this.collection(clazz))
}
/**
@@ -66,7 +71,7 @@ open class MongoQueryTyped(var repo: MongoTemplate, override var logger: ILogger
*/
protected fun <TView> collection(clazz: Class<TView>): String {
return if (this.collection.isEmpty()) {
this.logger?.warn(this, "查询集合参数[collection]值为空, 尝试使用View<${clazz.name}>名称解析集合")
this.logger?.info(this, "查询集合参数[collection]值为空, 尝试使用View<${clazz.name}>名称解析集合")
val collection = clazz.simpleName.removeSuffix("View").firstCharLowerCase()
if (!validViewCollection || this.repo.collectionExists(collection))
collection

View File

@@ -0,0 +1,48 @@
package com.synebula.gaea.mongo.repository
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepository
import com.synebula.gaea.mongo.whereId
import org.springframework.data.mongodb.core.MongoTemplate
/**
* 实现IAggregateRoot的mongo仓储类
* @param repo MongoRepo对象
*/
class MongoRepository<TAggregateRoot : IAggregateRoot<String>>(private var repo: MongoTemplate)
: IRepository<TAggregateRoot, String> {
/**
* 仓储的对象类
*/
override var clazz: Class<TAggregateRoot>? = null
/**
* 构造
* @param clazz 仓储Domain对象
* @param repo MongoRepo对象
*/
constructor(clazz: Class<TAggregateRoot>, repo: MongoTemplate) : this(repo) {
this.clazz = clazz
}
override fun add(obj: TAggregateRoot) {
this.repo.save(obj)
}
override fun update(obj: TAggregateRoot) {
this.repo.save(obj)
}
override fun remove(id: String) {
this.repo.remove(whereId(id), this.clazz!!)
}
override fun get(id: String): TAggregateRoot {
return this.repo.findOne(whereId(id), clazz!!) as TAggregateRoot
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> get(id: TKey, clazz: Class<TAggregateRoot>): TAggregateRoot {
return this.repo.findOne(whereId(id.toString()), clazz) as TAggregateRoot
}
}

View File

@@ -0,0 +1,30 @@
package com.synebula.gaea.mongo.repository
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepositoryTyped
import com.synebula.gaea.mongo.whereId
import org.springframework.data.mongodb.core.MongoTemplate
/**
* 实现ITypedRepository的mongo仓储类
* @param repo MongoRepo对象
*/
open class MongoRepositoryTyped(private var repo: MongoTemplate)
: IRepositoryTyped {
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> remove(id: TKey, clazz: Class<TAggregateRoot>) {
this.repo.remove(whereId(id), clazz)
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> get(id: TKey, clazz: Class<TAggregateRoot>): TAggregateRoot {
return this.repo.findOne(whereId(id), clazz) as TAggregateRoot
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> update(obj: TAggregateRoot, clazz: Class<TAggregateRoot>) {
this.repo.save(obj)
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> add(obj: TAggregateRoot, clazz: Class<TAggregateRoot>) {
this.repo.save(obj)
}
}

View File

@@ -1,153 +0,0 @@
package com.synebula.gaea.query.mongo
import com.synebula.gaea.log.ILogger
import com.synebula.gaea.query.OrderType
import org.springframework.data.domain.Sort
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
import java.lang.reflect.Field
/**
* 声明了Mongo查询的特有方法
*/
interface IMongoQuery {
/**
* 日志组件
*/
var logger: ILogger?
/**
* 系统类型
*/
private fun systemClass() = arrayOf(
"String",
"Date",
"Int",
"Double",
"Float",
"BigDecimal",
"Decimal")
/**
* 获取ID查询条件
*
* @param id 业务ID
*/
fun <TKey> idQuery(id: TKey): Query = Query(Criteria("_id").isEqualTo(id))
/**
* 获取视图对象的字段列表
*
* @param clazz 视图对象类型
*/
fun <TView> fields(clazz: Class<TView>): List<String> {
return analyseFields(clazz.declaredFields)
}
/**
* 获取查询条件
*
* @param query 查询条件
* @param fields 字段列表
*/
fun select(query: Query, fields: Array<String>): Query {
fields.forEach {
query.fields().include(it)
}
return query
}
/**
* 根据参数获取查询条件
*
* @param query 查询条件
* @param params 参数列表
* @param clazz 视图类对象
*/
fun <TView> where(query: Query, params: Map<String, Any>?, clazz: Class<TView>): Query {
val criteria = Criteria()
if (params != null) {
for (param in params) {
val value = this.changeFieldType(param.key, param.value, clazz)
criteria.and(param.key).isEqualTo(value)
}
}
return query.addCriteria(criteria)
}
/**
* 获取排序对象
*
* @param orders 排序条件字段
*/
fun order(orders: Map<String, OrderType>?): Sort {
val orderList = mutableListOf<Sort.Order>()
orders?.forEach {
orderList.add(Sort.Order(Sort.Direction.valueOf(it.value.name), it.key))
}
return if (orderList.size == 0)
Sort.by("_id")
else
Sort.by(orderList)
}
/**
* 分析视图字段对象,获取深层字段列表
*
* @param fields 需要分析的视图字段
*/
fun analyseFields(fields: Array<Field>): List<String> {
val names = mutableListOf<String>()
fields.forEach { field ->
names.add(field.name)
if (!field.type.isPrimitive
&& !field.type.isArray
&& !this.systemClass().contains(field.type.simpleName))
names.addAll(this.analyseFields(field.type.declaredFields).map { "${field.name}.$it" })
}
return names
}
/**
* 转换查询条件指定字段的类型
*
* @param key 字段名称
* @param value 字段值
* @param clazz 视图类对象
*/
fun <TView> changeFieldType(key: String, value: Any, clazz: Class<TView>): Any? {
val getter = clazz.getMethod("get${key.substring(0, 1).toUpperCase()}${key.substring(1)}")
return this.convertType(value.toString(), getter.returnType)
}
/**
* 转换String到指定类型
*
* @param value 字段值
* @param clazz 视图类对象
*/
fun convertType(value: String, clazz: Class<*>): Any? {
if (!clazz.isPrimitive) { // 判断基本类型
if (clazz == String::class.java) { // 如果是string则直接返回
return value
}
// 如果不为null 则通过反射实例一个对象返回
return if ("" == value) null else clazz.getConstructor(String::class.java).newInstance(value)
}
// 下面处理基本类型,返回包装类
return when (clazz.name) {
"int" -> Integer.parseInt(value)
"byte" -> java.lang.Byte.parseByte(value)
"boolean" -> java.lang.Boolean.parseBoolean(value)
"double" -> java.lang.Double.parseDouble(value)
"float" -> java.lang.Float.parseFloat(value)
"long" -> java.lang.Long.parseLong(value)
"short" -> java.lang.Short.parseShort(value)
else -> value
}
}
}

View File

@@ -1,14 +0,0 @@
package com.synebula.gaea.repository.mongo
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
interface IMongoRepository {
/**
* 获取ID查询条件
*
* @param id 业务ID
*/
fun <TKey> idQuery(id: TKey): Query = Query(Criteria("_id").isEqualTo(id))
}

View File

@@ -1,50 +0,0 @@
package com.synebula.gaea.repository.mongo
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepository
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
/**
* 实现IAggregateRoot的mongo仓储类
* @param repo MongoRepo对象
*/
class MongoRepository<TAggregateRoot : IAggregateRoot<String>>(private var repo: MongoTemplate)
: IRepository<TAggregateRoot, String>, IMongoRepository {
/**
* 仓储的对象类
*/
override var clazz: Class<TAggregateRoot>? = null
/**
* 构造
* @param clazz 仓储Domain对象
* @param repo MongoRepo对象
*/
constructor(clazz: Class<TAggregateRoot>, repo: MongoTemplate) : this(repo) {
this.clazz = clazz
}
override fun add(obj: TAggregateRoot) {
this.repo.save(obj)
}
override fun update(obj: TAggregateRoot) {
this.repo.save(obj)
}
override fun remove(id: String) {
this.repo.remove(idQuery(id), this.clazz!!)
}
override fun get(id: String): TAggregateRoot {
return this.repo.findOne(idQuery(id), clazz!!) as TAggregateRoot
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> get(id: TKey, clazz: Class<TAggregateRoot>): TAggregateRoot {
return this.repo.findOne(idQuery(id.toString()), clazz) as TAggregateRoot
}
}

View File

@@ -1,34 +0,0 @@
package com.synebula.gaea.repository.mongo
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepositoryTyped
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.isEqualTo
/**
* 实现ITypedRepository的mongo仓储类
* @param repo MongoRepo对象
*/
open class MongoRepositoryTyped(private var repo: MongoTemplate)
: IRepositoryTyped, IMongoRepository {
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> remove(id: TKey, clazz: Class<TAggregateRoot>) {
this.repo.remove(idQuery(id), clazz)
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> get(id: TKey, clazz: Class<TAggregateRoot>): TAggregateRoot {
return this.repo.findOne(idQuery(id), clazz) as TAggregateRoot
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> update(obj: TAggregateRoot, clazz: Class<TAggregateRoot>) {
this.repo.save(obj)
}
override fun <TAggregateRoot : IAggregateRoot<TKey>, TKey> add(obj: TAggregateRoot, clazz: Class<TAggregateRoot>) {
this.repo.save(obj)
}
}