feat:1.7 重构 service query 的组织模式

This commit is contained in:
2024-09-30 22:55:02 +08:00
parent de8fc0256f
commit 99877eddcc
17 changed files with 108 additions and 116 deletions

View File

@@ -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) {

View File

@@ -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

View File

@@ -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> {

View File

@@ -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)
}
}

View File

@@ -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> {

View File

@@ -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
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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))
}

View File

@@ -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)
}
}

View File

@@ -13,12 +13,3 @@ dependencies {
api("org.springframework.boot:spring-boot-starter-aop:$spring_version")
}
publishing {
publications {
publish(MavenPublication) {
from components.java
}
}
}

View File

@@ -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>
}

View File

@@ -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>
}

View File

@@ -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

View File

@@ -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
/**
* 增加对象
*