|
@@ -0,0 +1,719 @@
|
|
|
+/*
|
|
|
+ * *********************************************************************************************************************
|
|
|
+ *
|
|
|
+ * !!
|
|
|
+ * .F88X
|
|
|
+ * X8888Y
|
|
|
+ * .}888888N;
|
|
|
+ * i888888N; .:! .I$WI:
|
|
|
+ * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
|
|
|
+ * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
|
|
|
+ * +888888N; .8888888Y "&&8Y.}8,
|
|
|
+ * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
|
|
|
+ * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
|
|
|
+ * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
|
|
|
+ * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
|
|
|
+ * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
|
|
|
+ * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
|
|
|
+ * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
|
|
|
+ * .:R888888I
|
|
|
+ * .&888888I Copyright (c) 2016-2020. 博锐尚格科技股份有限公司
|
|
|
+ * ~8888'
|
|
|
+ * .!88~ All rights reserved.
|
|
|
+ *
|
|
|
+ * *********************************************************************************************************************
|
|
|
+ */
|
|
|
+
|
|
|
+package com.persagy.service
|
|
|
+
|
|
|
+import com.persagy.base.extensions.getAllDeclaredField
|
|
|
+import com.persagy.base.extensions.toJson
|
|
|
+import com.persagy.database.*
|
|
|
+import com.persagy.database.extensions.keyFieldList
|
|
|
+import com.persagy.database.extensions.keyValue
|
|
|
+import com.persagy.service.models.SCascadeQuery
|
|
|
+import com.persagy.service.models.annotations.SCascade
|
|
|
+import com.persagy.service.models.annotations.SCascadeCount
|
|
|
+import java.lang.reflect.Field
|
|
|
+import java.lang.reflect.ParameterizedType
|
|
|
+
|
|
|
+/**
|
|
|
+ * 服务类基类
|
|
|
+ *
|
|
|
+ * @author 庞利祥 <sybotan@126.com>
|
|
|
+ */
|
|
|
+open class SBaseService<ENTITY: Any> {
|
|
|
+
|
|
|
+ /** 数据访问对象 */
|
|
|
+ protected var baseDao: SAbstractDao<ENTITY>
|
|
|
+
|
|
|
+ /** 实体类类型 */
|
|
|
+ val entityClass: Class<ENTITY>
|
|
|
+ get() = baseDao.entityClass
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ *
|
|
|
+ * @param entityClazz 实体类
|
|
|
+ */
|
|
|
+ constructor(entityClazz: Class<ENTITY>) {
|
|
|
+ baseDao = daoFactory(entityClazz)
|
|
|
+ } // Constructor()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ *
|
|
|
+ * @param daoObject 数据访问对象
|
|
|
+ */
|
|
|
+ constructor(daoObject: SAbstractDao<ENTITY>) {
|
|
|
+ baseDao = daoObject
|
|
|
+ } // Constructor()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Dao对象工厂类
|
|
|
+ *
|
|
|
+ * @param entityClazz 实体类
|
|
|
+ * @return 访问实体的Dao对象
|
|
|
+ */
|
|
|
+ private fun daoFactory(entityClazz: Class<ENTITY>): SAbstractDao<ENTITY> {
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ val factory = Class.forName("com.persagy.mybatis.SDaoFactory").newInstance() as SAbstractDaoFactory<ENTITY>
|
|
|
+ return factory.createDao(entityClazz)
|
|
|
+ } // Fun daoFactory
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在数据库中插入实体
|
|
|
+ *
|
|
|
+ * @param entity 插入数据库的实体
|
|
|
+ * @return 插入是否成功
|
|
|
+ */
|
|
|
+ open fun insert(entity: ENTITY): Boolean {
|
|
|
+ return baseDao.insert(entity)
|
|
|
+ } // Fun insert()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在数据库中插入实体
|
|
|
+ *
|
|
|
+ * @param entity 插入数据库的实体
|
|
|
+ * @return 插入是否成功
|
|
|
+ */
|
|
|
+ open fun replace(entity: ENTITY): Boolean {
|
|
|
+ return baseDao.replace(entity)
|
|
|
+ } // Fun replace()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除实体
|
|
|
+ *
|
|
|
+ * @param entity 被删除的实体
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun delete(entity: ENTITY): Boolean {
|
|
|
+ return baseDao.delete(entity)
|
|
|
+ } // Fun delete()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件删除
|
|
|
+ *
|
|
|
+ * @param args 删除条件
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun delete(vararg args: Pair<String, Any>): Boolean {
|
|
|
+ return baseDao.delete(*args)
|
|
|
+ } // Fun delete()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件删除
|
|
|
+ *
|
|
|
+ * @param args 删除条件
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun delete(vararg args: SFilter): Boolean {
|
|
|
+ return baseDao.delete(*args)
|
|
|
+ } // Fun delete()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件删除
|
|
|
+ *
|
|
|
+ * @param args 删除条件
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun delete(args: List<SFilter>): Boolean {
|
|
|
+ return baseDao.delete(args)
|
|
|
+ } // Fun delete()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件删除
|
|
|
+ *
|
|
|
+ * @param query 删除条件
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun delete(query: String): Boolean {
|
|
|
+ return baseDao.delete(query)
|
|
|
+ } // Fun delete()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除所有记录
|
|
|
+ *
|
|
|
+ * @return 删除是否成功
|
|
|
+ */
|
|
|
+ open fun deleteAll(): Boolean {
|
|
|
+ return baseDao.deleteAll()
|
|
|
+ } // Fun deleteAll()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新实体
|
|
|
+ *
|
|
|
+ * @param entity 更新实体
|
|
|
+ * @param projection 将被更新的字段列表(以逗号分隔),为空表示更新所有非空字段
|
|
|
+ * @return 更新是否成功
|
|
|
+ */
|
|
|
+ open fun update(entity: ENTITY, projection: ArrayList<String>? = null): Boolean {
|
|
|
+ return baseDao.update(entity, projection)
|
|
|
+ } // Fun update()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件更新
|
|
|
+ *
|
|
|
+ * @param projection 将被更新的字段列表(以逗号分隔),为空表示更新所有非空字段
|
|
|
+ * @param args 更新条件
|
|
|
+ * @return 更新是否成功
|
|
|
+ */
|
|
|
+ open fun update(entity: ENTITY, projection: ArrayList<String>?, vararg args: Pair<String, Any>): Boolean {
|
|
|
+ return baseDao.update(entity, projection, *args)
|
|
|
+ } // Fun update()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件更新
|
|
|
+ *
|
|
|
+ * @param projection 将被更新的字段列表(以逗号分隔),为空表示更新所有非空字段
|
|
|
+ * @param args 更新条件
|
|
|
+ * @return 更新是否成功
|
|
|
+ */
|
|
|
+ open fun update(entity: ENTITY, projection: ArrayList<String>?, vararg args: SFilter): Boolean {
|
|
|
+ return baseDao.update(entity, projection, *args)
|
|
|
+ } // Fun update()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件更新
|
|
|
+ *
|
|
|
+ * @param projection 将被更新的字段列表(以逗号分隔),为空表示更新所有非空字段
|
|
|
+ * @param args 更新条件
|
|
|
+ * @return 更新是否成功
|
|
|
+ */
|
|
|
+ open fun update(entity: ENTITY, projection: ArrayList<String>?, args: List<SFilter>): Boolean {
|
|
|
+ return baseDao.update(entity, projection, args)
|
|
|
+ } // Fun update()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件更新
|
|
|
+ *
|
|
|
+ * @param projection 将被更新的字段列表(以逗号分隔),为空表示更新所有非空字段
|
|
|
+ * @param query 更新条件
|
|
|
+ * @return 更新是否成功
|
|
|
+ */
|
|
|
+ open fun update(entity: ENTITY, projection: ArrayList<String>?, query: String): Boolean {
|
|
|
+ return baseDao.update(entity, projection, query)
|
|
|
+ } // Fun update()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询一条记录
|
|
|
+ *
|
|
|
+ * @param args 查询条件
|
|
|
+ */
|
|
|
+ open fun select(vararg args: Pair<String, Any>): SQueryBuilder<ENTITY> {
|
|
|
+ return baseDao.select(*args)
|
|
|
+ } // Fun select()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询记录
|
|
|
+ *
|
|
|
+ * @param args 查询条件
|
|
|
+ * @return 查询构造器
|
|
|
+ */
|
|
|
+ open fun select(vararg args: SFilter): SQueryBuilder<ENTITY> {
|
|
|
+ return baseDao.select(*args)
|
|
|
+ } // Fun select()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询记录
|
|
|
+ *
|
|
|
+ * @param args 查询条件
|
|
|
+ * @return 查询构造器
|
|
|
+ */
|
|
|
+ open fun select(args: List<SFilter>): SQueryBuilder<ENTITY> {
|
|
|
+ return baseDao.select(args)
|
|
|
+ } // Fun select()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询记录
|
|
|
+ *
|
|
|
+ * @param query 查询条件
|
|
|
+ * @return 查询构造器
|
|
|
+ */
|
|
|
+ open fun select(query: String?): SQueryBuilder<ENTITY> {
|
|
|
+ return baseDao.select(query)
|
|
|
+ } // Fun select()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据条件查询所有记录
|
|
|
+ *
|
|
|
+ * @return 查找的记录
|
|
|
+ */
|
|
|
+ open fun selectAll(): SQueryBuilder<ENTITY> {
|
|
|
+ var builder = baseDao.selectAll()
|
|
|
+
|
|
|
+ builder.limit(9999999)
|
|
|
+ return builder
|
|
|
+ } // Fun selectAll()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行查询操作
|
|
|
+ *
|
|
|
+ * @param builder 查询查询构造器
|
|
|
+ * @return 查询到的记录
|
|
|
+ */
|
|
|
+ open fun execQuery(builder: SQueryBuilder<ENTITY>): ArrayList<ENTITY> {
|
|
|
+ return baseDao.execQuery(builder)
|
|
|
+ } // Fun execQuery()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行查询操作
|
|
|
+ *
|
|
|
+ * @param builder 查询查询构造器
|
|
|
+ * @return 查询到的记录数
|
|
|
+ */
|
|
|
+ open fun execCount(builder: SQueryBuilder<ENTITY>): Long {
|
|
|
+ return baseDao.execCount(builder)
|
|
|
+ } // Fun execQuery()
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
+ // 回调函数
|
|
|
+ /**
|
|
|
+ * 创建对象前回调函数
|
|
|
+ *
|
|
|
+ * @param entity 创建前的回调函数
|
|
|
+ * @return 返回true,可以创建对象
|
|
|
+ */
|
|
|
+ protected open fun onCreateBefore(entity: ENTITY): Boolean {
|
|
|
+ return true
|
|
|
+ } // Fun onCreateBefore()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建成功后回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 创建成功对象列表
|
|
|
+ */
|
|
|
+ protected open fun onCreateSuccess(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onCreateSuccess()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建失败回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 创建失败对象列表
|
|
|
+ */
|
|
|
+ protected open fun onCreateFailure(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onCreateFailure()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除前回调函数
|
|
|
+ *
|
|
|
+ * @param entity 创建前的回调函数
|
|
|
+ * @return 返回true,可以删除对象
|
|
|
+ */
|
|
|
+ protected open fun onDeleteBefore(entity: ENTITY): Boolean {
|
|
|
+ return true
|
|
|
+ } // Fun onCreateEntity()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除成功回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 删除成功对象列表
|
|
|
+ */
|
|
|
+ protected open fun onDeleteSuccess(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onDeleteSuccess()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除失败回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 删除失败对象列表
|
|
|
+ */
|
|
|
+ protected open fun onDeleteFailure(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onDeleteFailure()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新前回调函数
|
|
|
+ *
|
|
|
+ * @param entity 创建前的回调函数
|
|
|
+ */
|
|
|
+ protected open fun onUpdateBefore(entity: ENTITY): Boolean {
|
|
|
+ return true
|
|
|
+ } // Fun onCreateEntity()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新成功能回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 更新成功对象列表
|
|
|
+ */
|
|
|
+ protected open fun onUpdateSuccess(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onUpdateSuccess()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新失败回调函数
|
|
|
+ *
|
|
|
+ * @param entityList 更新失败对象列表
|
|
|
+ */
|
|
|
+ protected open fun onUpdateFailure(entityList: ArrayList<ENTITY>) {
|
|
|
+ } // Fun onUpdateFailure()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询前回调函数
|
|
|
+ *
|
|
|
+ * @param queryBuilder 查询构造器
|
|
|
+ */
|
|
|
+ protected open fun onQueryBefore(queryBuilder: SQueryBuilder<ENTITY>) {
|
|
|
+ } // Fun onQueryBefore()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询成功回调函数
|
|
|
+ *
|
|
|
+ * @param pageInfo 页面信息
|
|
|
+ */
|
|
|
+ protected open fun onQuerySuccess(pageInfo: SPageQueryInfo<ENTITY>) {
|
|
|
+ } // Fun onQuerySuccess()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统计个数前回调函数
|
|
|
+ *
|
|
|
+ * @param queryBuilder 查询构造器
|
|
|
+ */
|
|
|
+ protected open fun onCountBefore(queryBuilder: SQueryBuilder<ENTITY>) {
|
|
|
+ } // Fun onQueryBefore()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统计个数成功回调函数
|
|
|
+ *
|
|
|
+ * @param count 统计结果
|
|
|
+ */
|
|
|
+ protected open fun onCountSuccess(count: Long) {
|
|
|
+ } // Fun onCountSuccess()
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
+ // 级联操作相关
|
|
|
+ /**
|
|
|
+ * 进行级联查询处理
|
|
|
+ *
|
|
|
+ * @param entityList 实体列表
|
|
|
+ * @param cascadeList 级联请求列表
|
|
|
+ */
|
|
|
+ fun processCascadeQuery(entityList: ArrayList<Any>, cascadeList: ArrayList<SCascadeQuery>) {
|
|
|
+ val entityMap = entityListToMap(entityList)
|
|
|
+ for (cascade in cascadeList) {
|
|
|
+ if (cascade.name == null) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获得级联相关信息。如果信息不完整,则退出
|
|
|
+ val cascadeField = entityClass.getAllDeclaredField(cascade.name!!) ?: continue
|
|
|
+ val cascadeQueryAnno = cascadeField.getAnnotation(SCascade::class.java)
|
|
|
+ val cascadeCountAnno = cascadeField.getAnnotation(SCascadeCount::class.java)
|
|
|
+ if (cascadeQueryAnno != null) {
|
|
|
+ cascadeQuery(entityMap, cascadeQueryAnno, cascadeField, cascade)
|
|
|
+ } else if (cascadeCountAnno != null) {
|
|
|
+ cascadeCount(entityMap, cascadeCountAnno, cascadeField, cascade)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+ } // Fun cascadeQuery()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 进行级联查询
|
|
|
+ *
|
|
|
+ * @param entityMap 实体Map
|
|
|
+ * @param cascadeAnno 级联查询注解
|
|
|
+ * @param cascadeField 级联查询对应的属性
|
|
|
+ * @param cascade 级联请求
|
|
|
+ */
|
|
|
+ private fun cascadeQuery(entityMap: HashMap<Any, Any>, cascadeAnno: SCascade, cascadeField: Field, cascade: SCascadeQuery) {
|
|
|
+ val cascadeClass = if (List::class.java.isAssignableFrom(cascadeField.type)) {
|
|
|
+ // 如果是1对多,或多对多。取列表的泛型
|
|
|
+ (cascadeField.genericType as ParameterizedType).actualTypeArguments[0] as Class<*>
|
|
|
+ } else {
|
|
|
+ // 如果为1对1,直接取对象类型
|
|
|
+ cascadeField.type
|
|
|
+ }
|
|
|
+
|
|
|
+ val idList = entityIdList(entityMap)
|
|
|
+ val relationList = baseDao.relationQuery(cascadeAnno.table, cascadeAnno.idColumn, cascadeAnno.childIdColumn, cascadeAnno.self, cascadeAnno.filter, idList)
|
|
|
+ // 如果未取到关联数据,则开始取下一个关联对象
|
|
|
+ if (relationList.size <= 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ val relationMap = relationListToMap(relationList)
|
|
|
+
|
|
|
+ /////////////////////////////////
|
|
|
+ // 开始构造级联查询
|
|
|
+ val service = SBaseService(cascadeClass)
|
|
|
+ val sqlBuilder = service.select(cascade.filters)
|
|
|
+ sqlBuilder.filter(SFilter.inList(cascadeClass.keyFieldList()[0].name, relationMap.keys.toList()))
|
|
|
+
|
|
|
+ /** 排序条件 */
|
|
|
+ if (null != cascade.orders) {
|
|
|
+ sqlBuilder.order(cascade.orders!!)
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 去重 */
|
|
|
+ if (null != cascade.distinct && cascade.distinct!!) {
|
|
|
+ sqlBuilder.distinct()
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 映射标志 */
|
|
|
+ if (null != cascade.projection) {
|
|
|
+ sqlBuilder.projection(cascade.projection!!)
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 分组统计 */
|
|
|
+ if (null != cascade.group && !cascade.group!!.nameList.isNullOrEmpty()) {
|
|
|
+ // 分组属性名列表
|
|
|
+ sqlBuilder.group(*cascade.group!!.nameList.toArray(emptyArray<String>()))
|
|
|
+ // 是否统计个数
|
|
|
+ sqlBuilder.count(cascade.group!!.count ?: false)
|
|
|
+ // 求和
|
|
|
+ if (!cascade.group!!.sumList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.sum(*cascade.group!!.sumList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 求平均值
|
|
|
+ if (!cascade.group!!.avgList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.avg(*cascade.group!!.avgList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 取最大值
|
|
|
+ if (!cascade.group!!.maxList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.max(*cascade.group!!.maxList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 取最小值
|
|
|
+ if (!cascade.group!!.minList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.min(*cascade.group!!.minList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ val childrenList = sqlBuilder.exec()
|
|
|
+ for (child in childrenList) {
|
|
|
+ val childKey = child::class.java.keyFieldList()[0].name
|
|
|
+ val id2 = child.keyValue(childKey)
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ val id1List = relationMap[id2] as ArrayList<Any?>?
|
|
|
+ id1List ?: continue
|
|
|
+ for (id1 in id1List) {
|
|
|
+ if (entityMap[id1] != null) {
|
|
|
+ fillCascadeObject(entityMap[id1]!!, child, cascadeField)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 如果需要进行级联查询 */
|
|
|
+ if (cascade.cascade != null && cascade.cascade!!.size > 0 &&
|
|
|
+ childrenList.size > 0) {
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ service.processCascadeQuery(childrenList as ArrayList<Any>, cascade.cascade!!)
|
|
|
+ }
|
|
|
+ return
|
|
|
+ } // Fun cascadeQuery()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 进行级联查询
|
|
|
+ *
|
|
|
+ * @param entityMap 实体Map
|
|
|
+ * @param cascadeAnno 级联查询注解
|
|
|
+ * @param cascadeField 级联查询对应的属性
|
|
|
+ * @param cascade 级联请求
|
|
|
+ */
|
|
|
+ private fun cascadeCount(entityMap: HashMap<Any, Any>, cascadeAnno: SCascadeCount, cascadeField: Field, cascade: SCascadeQuery) {
|
|
|
+ val idList = entityIdList(entityMap)
|
|
|
+ val relationList = baseDao.relationQuery(cascadeAnno.table, cascadeAnno.idColumn, cascadeAnno.childIdColumn, cascadeAnno.self, cascadeAnno.filter, idList)
|
|
|
+ // 如果未取到关联数据,则开始取下一个关联对象
|
|
|
+ if (relationList.size <= 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ val relationMap = relationListToMap(relationList)
|
|
|
+
|
|
|
+ /////////////////////////////////
|
|
|
+ // 开始构造级联查询
|
|
|
+ val service = SBaseService(cascadeAnno.childClass.java)
|
|
|
+ val sqlBuilder = service.select(cascade.filters)
|
|
|
+ sqlBuilder.filter(SFilter.inList(cascadeAnno.childClass.java.keyFieldList()[0].name, relationMap.keys.toList()))
|
|
|
+
|
|
|
+ /** 排序条件 */
|
|
|
+ if (null != cascade.orders) {
|
|
|
+ sqlBuilder.order(cascade.orders!!)
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 去重 */
|
|
|
+ if (null != cascade.distinct && cascade.distinct!!) {
|
|
|
+ sqlBuilder.distinct()
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 映射标志 */
|
|
|
+ if (null != cascade.projection) {
|
|
|
+ sqlBuilder.projection(cascade.projection!!)
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 分组统计 */
|
|
|
+ if (null != cascade.group && !cascade.group!!.nameList.isNullOrEmpty()) {
|
|
|
+ // 分组属性名列表
|
|
|
+ sqlBuilder.group(*cascade.group!!.nameList.toArray(emptyArray<String>()))
|
|
|
+ // 是否统计个数
|
|
|
+ sqlBuilder.count(cascade.group!!.count ?: false)
|
|
|
+ // 求和
|
|
|
+ if (!cascade.group!!.sumList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.sum(*cascade.group!!.sumList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 求平均值
|
|
|
+ if (!cascade.group!!.avgList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.avg(*cascade.group!!.avgList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 取最大值
|
|
|
+ if (!cascade.group!!.maxList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.max(*cascade.group!!.maxList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ // 取最小值
|
|
|
+ if (!cascade.group!!.minList.isNullOrEmpty()) {
|
|
|
+ sqlBuilder.min(*cascade.group!!.minList.toArray(emptyArray<String>()))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ val childrenList = sqlBuilder.exec()
|
|
|
+ for (child in childrenList) {
|
|
|
+ val childKey = child::class.java.keyFieldList()[0].name
|
|
|
+ val id2 = child.keyValue(childKey)
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ val id1List = relationMap[id2] as ArrayList<Any?>?
|
|
|
+ id1List ?: continue
|
|
|
+ for (id1 in id1List) {
|
|
|
+ if (entityMap[id1] != null) {
|
|
|
+ fillCascadeCount(entityMap[id1]!!, child, cascadeField)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+ } // Fun cascadeCount()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 为加速填充级联对象,将实体列表转换为map。
|
|
|
+ *
|
|
|
+ * @param entityList 实体列表
|
|
|
+ * @return 以Map形式存储的实体
|
|
|
+ */
|
|
|
+ private fun entityListToMap(entityList: ArrayList<Any>): HashMap<Any, Any> {
|
|
|
+ val map = HashMap<Any, Any>()
|
|
|
+ val key = entityClass.keyFieldList()[0]
|
|
|
+ for (entity in entityList) {
|
|
|
+ map[entity.keyValue(key.name)!!] = entity
|
|
|
+ }
|
|
|
+ return map
|
|
|
+ } // Fun entityMap()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得实体的Id列表
|
|
|
+ *
|
|
|
+ * @param entityMap 实体Map
|
|
|
+ * @return ID列表
|
|
|
+ */
|
|
|
+ private fun entityIdList(entityMap: HashMap<Any, Any>): ArrayList<Any> {
|
|
|
+ val idList = ArrayList<Any>()
|
|
|
+ for (entity in entityMap) {
|
|
|
+ val keyField = entity.value.javaClass.keyFieldList()[0]
|
|
|
+ val keyValue = entity.value.keyValue(keyField.name)!!
|
|
|
+ println("keyField=${keyField.toJson()}")
|
|
|
+ println("keyValue=${keyValue.toJson()}")
|
|
|
+ idList.add(keyValue)
|
|
|
+ }
|
|
|
+ return idList
|
|
|
+ } // Fun entityIdList()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将关系列表转换为Map
|
|
|
+ *
|
|
|
+ * @param cascadeList 被转换的列表
|
|
|
+ * @return 转换后的Map
|
|
|
+ */
|
|
|
+ private fun relationListToMap(cascadeList: List<HashMap<String, Any>>): HashMap<Any, ArrayList<Any>> {
|
|
|
+ val map = HashMap<Any, ArrayList<Any>>()
|
|
|
+ for (item in cascadeList) {
|
|
|
+ item["id2"] ?: continue
|
|
|
+
|
|
|
+ var list = map[item["id2"]!!]
|
|
|
+ if (list == null) {
|
|
|
+ list = ArrayList()
|
|
|
+ }
|
|
|
+ list.add(item["id1"]!!)
|
|
|
+ map[item["id2"]!!] = list
|
|
|
+ }
|
|
|
+ return map
|
|
|
+ } // Fun cascadeToMap()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 填级联对象
|
|
|
+ *
|
|
|
+ * @param entity 实体
|
|
|
+ * @param child 填入的对象
|
|
|
+ * @param field 填入的对象对应的实体类属性
|
|
|
+ */
|
|
|
+ private fun fillCascadeObject(entity: Any, child: Any?, field: Field) {
|
|
|
+ // 如果child为空,则返回
|
|
|
+ child ?: return
|
|
|
+
|
|
|
+ // 保存访问权限
|
|
|
+ val accessible = field.isAccessible
|
|
|
+ field.isAccessible = true
|
|
|
+
|
|
|
+ // 如果field是列表
|
|
|
+ if (List::class.java.isAssignableFrom(field.type)) {
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ var children = field.get(entity) as ArrayList<Any>?
|
|
|
+ if (children == null) {
|
|
|
+ children = ArrayList()
|
|
|
+ }
|
|
|
+ children.add(child)
|
|
|
+ field.set(entity, children)
|
|
|
+ } else {
|
|
|
+ // 如果field是对象
|
|
|
+ if (field.get(entity) == null) {
|
|
|
+ field.set(entity, child)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复访问权限
|
|
|
+ field.isAccessible = accessible
|
|
|
+ return
|
|
|
+ } // Fun fillCascadeObject()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 填级联对象
|
|
|
+ *
|
|
|
+ * @param entity 实体
|
|
|
+ * @param child 填入的对象
|
|
|
+ * @param field 填入的对象对应的实体类属性
|
|
|
+ */
|
|
|
+ private fun fillCascadeCount(entity: Any, child: Any?, field: Field) {
|
|
|
+ // 如果child为空,则返回
|
|
|
+ child ?: return
|
|
|
+
|
|
|
+ // 保存访问权限
|
|
|
+ val accessible = field.isAccessible
|
|
|
+ field.isAccessible = true
|
|
|
+
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ var count = field.get(entity) as? Int
|
|
|
+ if (count == null) {
|
|
|
+ count = 0
|
|
|
+ }
|
|
|
+ count++
|
|
|
+ field.set(entity, count)
|
|
|
+
|
|
|
+ // 恢复访问权限
|
|
|
+ field.isAccessible = accessible
|
|
|
+ return
|
|
|
+ } // Fun fillCascadeCount()
|
|
|
+} // Class SBaseService
|