feat:1.7 重构 service query 的组织模式
This commit is contained in:
27
build.gradle
27
build.gradle
@@ -22,7 +22,7 @@ buildscript {
|
||||
|
||||
subprojects {
|
||||
group 'com.synebula'
|
||||
version '1.6.0'
|
||||
version '1.7.0'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
@@ -66,16 +66,21 @@ subprojects {
|
||||
}
|
||||
|
||||
publishing {
|
||||
// repositories {
|
||||
// maven {
|
||||
// allowInsecureProtocol = true
|
||||
// url = "$nexus_url"
|
||||
// credentials {
|
||||
// username = "$nexus_usr"
|
||||
// password = "$nexus_pwd"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
repositories {
|
||||
maven {
|
||||
name = "Gitea"
|
||||
url = uri("https://git.synebula.com/api/packages/alex/maven")
|
||||
|
||||
credentials(HttpHeaderCredentials) {
|
||||
name = "Authorization"
|
||||
value = "token 1b9a13c1c75832c2f82beba8c8db340364eff7b1"
|
||||
}
|
||||
|
||||
authentication {
|
||||
header(HttpHeaderAuthentication)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
|
||||
@@ -20,8 +20,9 @@ import org.springframework.beans.factory.annotation.Autowired
|
||||
open class DomainApplication<TCommand : ICommand, TView, ID>(
|
||||
override var name: String,
|
||||
override var service: IService<ID>,
|
||||
override var query: IQuery<TView, ID>,
|
||||
override var logger: ILogger,
|
||||
override var query: IQuery,
|
||||
override var clazz: Class<TView>,
|
||||
override var logger: ILogger
|
||||
) : ICommandApp<TCommand, ID>, IQueryApp<TView, ID> {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -20,7 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired
|
||||
open class RecordApplication<TRoot : IAggregateRoot<ID>, ID>(
|
||||
override var name: String,
|
||||
override var service: IService<TRoot, ID>,
|
||||
override var query: IQuery<TRoot, ID>,
|
||||
override var query: IQuery,
|
||||
override var clazz: Class<TRoot>,
|
||||
override var logger: ILogger,
|
||||
) : ISimpleCommandApp<TRoot, ID>, IQueryApp<TRoot, ID> {
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ interface IQueryApp<TView, ID> : IApplication {
|
||||
/**
|
||||
* 查询服务
|
||||
*/
|
||||
var query: IQuery<TView, ID>
|
||||
var query: IQuery
|
||||
|
||||
var clazz: Class<TView>
|
||||
|
||||
@Method("获取数据")
|
||||
@GetMapping("/{id:.+}")
|
||||
fun get(@PathVariable id: ID): HttpMessage {
|
||||
val data = this.query.get(id)
|
||||
val data = this.query.get(id, clazz)
|
||||
val msg = this.httpMessageFactory.create()
|
||||
msg.data = data
|
||||
return msg
|
||||
@@ -27,7 +29,7 @@ interface IQueryApp<TView, ID> : IApplication {
|
||||
@Method("获取列表数据")
|
||||
@GetMapping
|
||||
fun list(@RequestParam params: LinkedHashMap<String, String>): HttpMessage {
|
||||
val data = this.query.list(params)
|
||||
val data = this.query.list(params, clazz)
|
||||
return this.httpMessageFactory.create(data)
|
||||
}
|
||||
|
||||
@@ -39,7 +41,7 @@ interface IQueryApp<TView, ID> : IApplication {
|
||||
@RequestParam parameters: LinkedHashMap<String, String>
|
||||
): HttpMessage {
|
||||
val params = Params(page, size, parameters)
|
||||
val data = this.query.paging(params)
|
||||
val data = this.query.paging(params, clazz)
|
||||
return this.httpMessageFactory.create(data)
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ import org.springframework.beans.factory.annotation.Autowired
|
||||
*/
|
||||
open class QueryApp<TView, ID>(
|
||||
override var name: String,
|
||||
override var query: IQuery<TView, ID>,
|
||||
override var query: IQuery,
|
||||
override var clazz: Class<TView>,
|
||||
override var logger: ILogger,
|
||||
) : IQueryApp<TView, ID> {
|
||||
|
||||
|
||||
@@ -3,18 +3,20 @@ package com.synebula.gaea.jpa
|
||||
import com.synebula.gaea.db.query.IQuery
|
||||
import com.synebula.gaea.db.query.Page
|
||||
import com.synebula.gaea.db.query.Params
|
||||
import com.synebula.gaea.jpa.proxy.method.resolver.PageMethodResolver
|
||||
import jakarta.persistence.EntityManager
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.jpa.domain.Specification
|
||||
import org.springframework.data.jpa.repository.support.SimpleJpaRepository
|
||||
|
||||
class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: EntityManager) : IQuery<TView, ID> {
|
||||
protected var repo: SimpleJpaRepository<TView, ID>
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class JpaQuery(protected var entityManager: EntityManager) : IQuery {
|
||||
protected var repos = mutableMapOf<Class<*>, SimpleJpaRepository<*, *>>()
|
||||
|
||||
init {
|
||||
repo = SimpleJpaRepository<TView, ID>(clazz, entityManager)
|
||||
}
|
||||
|
||||
override operator fun get(id: ID): TView? {
|
||||
val view = this.repo.findById(id!!)
|
||||
override operator fun <TView, ID> get(id: ID, clazz: Class<TView>): TView? {
|
||||
val repo = this.getJpaRepository(clazz)
|
||||
val view = repo.findById(id!!)
|
||||
return if (view.isPresent) view.get() else null
|
||||
}
|
||||
|
||||
@@ -25,9 +27,10 @@ class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: Entit
|
||||
* @param params 查询条件。
|
||||
* @return 视图列表
|
||||
*/
|
||||
override fun list(params: Map<String, String>?): List<TView> {
|
||||
// method proxy in JpaRepositoryProxy [SimpleJpaRepository]
|
||||
return emptyList()
|
||||
override fun <TView> list(params: Map<String, String>?, clazz: Class<TView>): List<TView> {
|
||||
val repo = this.getJpaRepository(clazz)
|
||||
val spec = params?.toSpecification(clazz) as Specification<TView>
|
||||
return repo.findAll(spec)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,9 +39,10 @@ class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: Entit
|
||||
* @param params 查询条件。
|
||||
* @return 数量
|
||||
*/
|
||||
override fun count(params: Map<String, String>?): Int {
|
||||
// method proxy in JpaRepositoryProxy [SimpleJpaRepository]
|
||||
return -1
|
||||
override fun <TView> count(params: Map<String, String>?, clazz: Class<TView>): Long {
|
||||
val repo = this.getJpaRepository(clazz)
|
||||
val spec = params?.toSpecification(clazz) as Specification<TView>
|
||||
return repo.count(spec)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,9 +51,11 @@ class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: Entit
|
||||
* @param params 分页条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
override fun paging(params: Params): Page<TView> {
|
||||
// method proxy in JpaRepositoryProxy [SimpleJpaRepository]
|
||||
return Page()
|
||||
override fun <TView> paging(params: Params, clazz: Class<TView>): Page<TView> {
|
||||
val repo = this.getJpaRepository(clazz)
|
||||
val p = PageMethodResolver("findAll", clazz).mappingArguments(arrayOf(params))
|
||||
val page = repo.findAll(p[0] as Specification<TView>, p[1] as Pageable)
|
||||
return Page(page.number + 1, page.size, page.totalElements, page.content)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,9 +65,18 @@ class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: Entit
|
||||
*
|
||||
* @return 视图列表
|
||||
*/
|
||||
override fun range(field: String, params: List<Any>): List<TView> {
|
||||
override fun <TView> range(field: String, params: List<Any>, clazz: Class<TView>): List<TView> {
|
||||
// method proxy in JpaRepositoryProxy [SimpleJpaRepository]
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private fun <TView> getJpaRepository(clazz: Class<TView>): SimpleJpaRepository<TView, in Any> {
|
||||
if (this.repos.isNotEmpty() && this.repos.containsKey(clazz)) {
|
||||
return this.repos[clazz] as SimpleJpaRepository<TView, Any>
|
||||
} else {
|
||||
val r = SimpleJpaRepository<TView, Any>(clazz, entityManager)
|
||||
this.repos[clazz] = r
|
||||
return r
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.synebula.gaea.jpa
|
||||
|
||||
import com.synebula.gaea.domain.model.IAggregateRoot
|
||||
import com.synebula.gaea.domain.repository.IRepository
|
||||
import com.synebula.gaea.domain.repository.IRepositoryFactory
|
||||
import jakarta.persistence.EntityManager
|
||||
|
||||
class JpaRepositoryFactory(private var entityManager: EntityManager) : IRepositoryFactory {
|
||||
override fun createRawRepository(clazz: Class<*>): IRepository<*, *> {
|
||||
val constructor = JpaRepository::class.java.getConstructor(Class::class.java, EntityManager::class.java)
|
||||
return constructor.newInstance(clazz, this.entityManager)
|
||||
}
|
||||
|
||||
override fun <T : IAggregateRoot<I>, I> createRepository(clazz: Class<T>): IRepository<T, I> {
|
||||
return JpaRepository(clazz, this.entityManager)
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,6 @@ class PageMethodResolver(targetMethodName: String, clazz: Class<*>) : AbstractMe
|
||||
val page = result as Page<*>
|
||||
|
||||
// Page 页面从0开始 [com.synebula.gaea.query.Page as QueryPage]
|
||||
return QueryPage(page.number + 1, page.size, page.totalElements.toInt(), page.content)
|
||||
return QueryPage(page.number + 1, page.size, page.totalElements, page.content)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package com.synebula.gaea.mongodb.autoconfig
|
||||
|
||||
import com.synebula.gaea.db.context.IDbContext
|
||||
import com.synebula.gaea.domain.repository.IRepository
|
||||
import com.synebula.gaea.mongodb.db.query.MongodbQuery
|
||||
import com.synebula.gaea.mongodb.db.MongodbQuery
|
||||
import com.synebula.gaea.mongodb.repository.MongodbRepository
|
||||
import com.synebula.gaea.db.query.IQuery
|
||||
import com.synebula.gaea.reflect.getGenericInterface
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.synebula.gaea.mongodb.db.context
|
||||
package com.synebula.gaea.mongodb.db
|
||||
|
||||
import com.synebula.gaea.db.IEntity
|
||||
import com.synebula.gaea.db.context.IDbContext
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.synebula.gaea.mongodb.db.query
|
||||
package com.synebula.gaea.mongodb.db
|
||||
|
||||
|
||||
import com.synebula.gaea.ext.firstCharLowerCase
|
||||
@@ -15,19 +15,22 @@ import org.springframework.data.mongodb.core.MongoTemplate
|
||||
import org.springframework.data.mongodb.core.query.Criteria
|
||||
import org.springframework.data.mongodb.core.query.Query
|
||||
|
||||
open class MongodbQuery<TView, ID>(override var clazz: Class<TView>, var template: MongoTemplate) :
|
||||
IQuery<TView, ID> {
|
||||
/**
|
||||
* 实现IQuery的Mongodb查询类
|
||||
* @param template MongodbRepo对象
|
||||
*/
|
||||
open class MongodbQuery(var template: MongoTemplate) : IQuery {
|
||||
|
||||
/**
|
||||
* 使用View解析是collection时是否校验存在,默认不校验
|
||||
*/
|
||||
var validViewCollection = false
|
||||
|
||||
override fun get(id: ID): TView? {
|
||||
override fun <TView, ID> get(id: ID, clazz: Class<TView>): TView? {
|
||||
return this.template.findOne(whereId(id), clazz, this.collection(clazz))
|
||||
}
|
||||
|
||||
override fun list(params: Map<String, String>?): List<TView> {
|
||||
override fun <TView> list(params: Map<String, String>?, clazz: Class<TView>): List<TView> {
|
||||
val fields = this.fields(clazz)
|
||||
val query = Query()
|
||||
query.where(params, clazz)
|
||||
@@ -35,16 +38,16 @@ open class MongodbQuery<TView, ID>(override var clazz: Class<TView>, var templat
|
||||
return this.find(query, clazz)
|
||||
}
|
||||
|
||||
override fun count(params: Map<String, String>?): Int {
|
||||
override fun <TView> count(params: Map<String, String>?, clazz: Class<TView>): Long {
|
||||
val query = Query()
|
||||
return this.template.count(query.where(params, clazz), this.collection(clazz)).toInt()
|
||||
return this.template.count(query.where(params, clazz), this.collection(clazz))
|
||||
}
|
||||
|
||||
override fun paging(params: Params): Page<TView> {
|
||||
override fun <TView> paging(params: Params, clazz: Class<TView>): Page<TView> {
|
||||
val query = Query()
|
||||
val fields = this.fields(clazz)
|
||||
val result = Page<TView>(params.page, params.size)
|
||||
result.total = this.count(params.parameters)
|
||||
result.total = this.count(params.parameters, clazz)
|
||||
//如果总数和索引相同,说明该页没有数据,直接跳到上一页
|
||||
if (result.total == result.index) {
|
||||
params.page -= 1
|
||||
@@ -58,11 +61,11 @@ open class MongodbQuery<TView, ID>(override var clazz: Class<TView>, var templat
|
||||
return result
|
||||
}
|
||||
|
||||
override fun range(field: String, params: List<Any>): List<TView> {
|
||||
override fun <TView> range(field: String, params: List<Any>, clazz: Class<TView>): List<TView> {
|
||||
return this.find(Query.query(Criteria.where(field).`in`(params)), clazz)
|
||||
}
|
||||
|
||||
protected fun find(query: Query, clazz: Class<TView>): List<TView> {
|
||||
protected fun <TView> find(query: Query, clazz: Class<TView>): List<TView> {
|
||||
return this.template.find(query, clazz, this.collection(clazz))
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.synebula.gaea.mongodb.db.query
|
||||
|
||||
import com.synebula.gaea.db.query.IQuery
|
||||
import com.synebula.gaea.db.query.IQueryFactory
|
||||
import org.springframework.data.mongodb.core.MongoTemplate
|
||||
|
||||
class MongodbQueryFactory(var template: MongoTemplate) : IQueryFactory {
|
||||
|
||||
/**
|
||||
* 创建IQuery接口类型
|
||||
*/
|
||||
override fun createRawQuery(clazz: Class<*>): IQuery<*, *> {
|
||||
val constructor = MongodbQuery::class.java.getConstructor(Class::class.java, MongoTemplate::class.java)
|
||||
return constructor.newInstance(clazz, this.template)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建IQuery接口类型
|
||||
*/
|
||||
override fun <T, I> createQuery(clazz: Class<T>): IQuery<T, I> {
|
||||
return MongodbQuery(clazz, template)
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,3 @@ dependencies {
|
||||
|
||||
api("org.springframework.boot:spring-boot-starter-aop:$spring_version")
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
publish(MavenPublication) {
|
||||
from components.java
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,27 +5,22 @@ package com.synebula.gaea.db.query
|
||||
*
|
||||
* @author alex
|
||||
*/
|
||||
interface IQuery<TView, ID> {
|
||||
/**
|
||||
* 仓储的视图类
|
||||
*/
|
||||
var clazz: Class<TView>
|
||||
|
||||
interface IQuery {
|
||||
/**
|
||||
* 根据Key获取对象。
|
||||
*
|
||||
* @param id 对象Key。
|
||||
* @return 视图结果
|
||||
*/
|
||||
fun get(id: ID): TView?
|
||||
fun <TView, ID> get(id: ID, clazz: Class<TView>): TView?
|
||||
|
||||
/**
|
||||
* 根据实体类条件查询所有符合条件记录
|
||||
*`
|
||||
*
|
||||
* @param params 查询条件。
|
||||
* @return 视图列表
|
||||
*/
|
||||
fun list(params: Map<String, String>?): List<TView>
|
||||
fun <TView> list(params: Map<String, String>?, clazz: Class<TView>): List<TView>
|
||||
|
||||
/**
|
||||
* 根据条件查询符合条件记录的数量
|
||||
@@ -33,7 +28,7 @@ interface IQuery<TView, ID> {
|
||||
* @param params 查询条件。
|
||||
* @return 数量
|
||||
*/
|
||||
fun count(params: Map<String, String>?): Int
|
||||
fun <TView> count(params: Map<String, String>?, clazz: Class<TView>): Long
|
||||
|
||||
/**
|
||||
* 根据实体类条件查询所有符合条件记录(分页查询)
|
||||
@@ -41,7 +36,7 @@ interface IQuery<TView, ID> {
|
||||
* @param params 分页条件
|
||||
* @return 分页数据
|
||||
*/
|
||||
fun paging(params: Params): Page<TView>
|
||||
fun <TView> paging(params: Params, clazz: Class<TView>): Page<TView>
|
||||
|
||||
/**
|
||||
* 查询条件范围内数据。
|
||||
@@ -50,5 +45,5 @@ interface IQuery<TView, ID> {
|
||||
*
|
||||
* @return 视图列表
|
||||
*/
|
||||
fun range(field: String, params: List<Any>): List<TView>
|
||||
fun <TView> range(field: String, params: List<Any>, clazz: Class<TView>): List<TView>
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.synebula.gaea.db.query
|
||||
|
||||
/**
|
||||
* Query 工厂接口。 定义了Query的创建方法。
|
||||
*/
|
||||
interface IQueryFactory {
|
||||
|
||||
/**
|
||||
* 创建原始类型的IQuery接口类型
|
||||
*/
|
||||
fun createRawQuery(clazz: Class<*>): IQuery<*, *>
|
||||
|
||||
/**
|
||||
* 创建指定类型的IQuery接口类型
|
||||
*/
|
||||
fun <T, I> createQuery(clazz: Class<T>): IQuery<T, I>
|
||||
}
|
||||
@@ -13,13 +13,13 @@ data class Page<T>(var page: Int = 0, var size: Int = 0) {
|
||||
/**
|
||||
* 总数据量。
|
||||
*/
|
||||
var total: Int = 0
|
||||
var total: Long = 0
|
||||
|
||||
/**
|
||||
* 数据索引,从0开始。表示数据在总量的第几条。(index = (page - 1) * size )
|
||||
*/
|
||||
val index: Int
|
||||
get() = (page - 1) * size
|
||||
val index: Long
|
||||
get() = (page - 1) * size.toLong()
|
||||
|
||||
/**
|
||||
* 结果数据。
|
||||
@@ -36,7 +36,7 @@ data class Page<T>(var page: Int = 0, var size: Int = 0) {
|
||||
* @param data 结果数据。
|
||||
*/
|
||||
|
||||
constructor(page: Int, size: Int, total: Int, data: List<T>) : this(page, size) {
|
||||
constructor(page: Int, size: Int, total: Long, data: List<T>) : this(page, size) {
|
||||
this.page = page
|
||||
this.size = size
|
||||
this.total = total
|
||||
|
||||
@@ -24,9 +24,10 @@ open class Service<TRoot : IAggregateRoot<ID>, ID>(
|
||||
protected open var clazz: Class<TRoot>,
|
||||
protected open var repository: IRepository<TRoot, ID>,
|
||||
protected open var mapper: IObjectMapper,
|
||||
protected open var bus: IBus<Any>? = null
|
||||
) : IService<ID> {
|
||||
|
||||
protected open var bus: IBus<Any>? = null
|
||||
|
||||
/**
|
||||
* 增加对象
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user