添加文件

This commit is contained in:
2024-06-29 20:00:05 +08:00
parent 54b7cedac6
commit 48a24b99e1
53 changed files with 353 additions and 550 deletions

View File

@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
buildscript { buildscript {
ext { ext {
jvm_version = '21' jvm_version = '21'
@@ -7,6 +9,7 @@ buildscript {
repositories { repositories {
mavenLocal() mavenLocal()
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/central' } maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://maven.aliyun.com/repository/public' }
mavenCentral() mavenCentral()
@@ -52,10 +55,14 @@ subprojects {
sourceCompatibility = "$jvm_version" sourceCompatibility = "$jvm_version"
targetCompatibility = "$jvm_version" targetCompatibility = "$jvm_version"
compileKotlin { compileKotlin {
kotlinOptions.jvmTarget = "$jvm_version" compilerOptions {
jvmTarget = JvmTarget.valueOf("JVM_$jvm_version")
}
} }
compileTestKotlin { compileTestKotlin {
kotlinOptions.jvmTarget = "$jvm_version" compilerOptions {
jvmTarget = JvmTarget.valueOf("JVM_$jvm_version")
}
} }
publishing { publishing {

View File

@@ -24,7 +24,7 @@ open class Cache<K, V>(expire: Int) : ICache<K, V> {
} }
override fun add(key: K, value: V) { override fun add(key: K, value: V) {
this.guavaCache.put(key, value) this.guavaCache.put(key!!, value!!)
} }
/** /**

View File

@@ -3,10 +3,10 @@ package com.synebula.gaea.app.controller
import com.synebula.gaea.app.controller.cmd.ICommandApp import com.synebula.gaea.app.controller.cmd.ICommandApp
import com.synebula.gaea.app.controller.query.IQueryApp import com.synebula.gaea.app.controller.query.IQueryApp
import com.synebula.gaea.data.message.HttpMessageFactory import com.synebula.gaea.data.message.HttpMessageFactory
import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.domain.service.ICommand import com.synebula.gaea.domain.service.ICommand
import com.synebula.gaea.domain.service.IService import com.synebula.gaea.domain.service.IService
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
import com.synebula.gaea.query.IQuery
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
/** /**
@@ -17,7 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired
* @param query 业务查询服务 * @param query 业务查询服务
* @param logger 日志组件 * @param logger 日志组件
*/ */
open class Application<TCommand : ICommand, TView, ID>( open class DomainApplication<TCommand : ICommand, TView, ID>(
override var name: String, override var name: String,
override var service: IService<ID>, override var service: IService<ID>,
override var query: IQuery<TView, ID>, override var query: IQuery<TView, ID>,

View File

@@ -3,10 +3,10 @@ package com.synebula.gaea.app.controller
import com.synebula.gaea.app.controller.cmd.ISimpleCommandApp import com.synebula.gaea.app.controller.cmd.ISimpleCommandApp
import com.synebula.gaea.app.controller.query.IQueryApp import com.synebula.gaea.app.controller.query.IQueryApp
import com.synebula.gaea.data.message.HttpMessageFactory import com.synebula.gaea.data.message.HttpMessageFactory
import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.service.ISimpleService
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
import com.synebula.gaea.query.IQuery import com.synebula.gaea.record.service.IService
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
/** /**
@@ -17,14 +17,13 @@ import org.springframework.beans.factory.annotation.Autowired
* @param query 业务查询服务 * @param query 业务查询服务
* @param logger 日志组件 * @param logger 日志组件
*/ */
open class SimpleApplication<TRoot : IAggregateRoot<ID>, ID>( open class RecordApplication<TRoot : IAggregateRoot<ID>, ID>(
override var name: String, override var name: String,
override var service: ISimpleService<TRoot, ID>, override var service: IService<TRoot, ID>,
override var query: IQuery<TRoot, ID>, override var query: IQuery<TRoot, ID>,
override var logger: ILogger, override var logger: ILogger,
) : ISimpleCommandApp<TRoot, ID>, IQueryApp<TRoot, ID> { ) : ISimpleCommandApp<TRoot, ID>, IQueryApp<TRoot, ID> {
@Autowired @Autowired
override lateinit var httpMessageFactory: HttpMessageFactory override lateinit var httpMessageFactory: HttpMessageFactory
} }

View File

@@ -4,7 +4,7 @@ import com.synebula.gaea.app.controller.IApplication
import com.synebula.gaea.data.message.HttpMessage import com.synebula.gaea.data.message.HttpMessage
import com.synebula.gaea.data.message.Status import com.synebula.gaea.data.message.Status
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.service.ISimpleService import com.synebula.gaea.record.service.IService
import com.synebula.gaea.spring.aop.annotation.Method import com.synebula.gaea.spring.aop.annotation.Method
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
@@ -16,12 +16,13 @@ import org.springframework.web.bind.annotation.*
* @since 2020-05-15 * @since 2020-05-15
*/ */
interface ISimpleCommandApp<TRoot : IAggregateRoot<ID>, ID> : IApplication { interface ISimpleCommandApp<TRoot : IAggregateRoot<ID>, ID> : IApplication {
var service: ISimpleService<TRoot, ID> var service: IService<TRoot, ID>
@PostMapping @PostMapping
@Method("添加") @Method("添加")
fun add(@RequestBody entity: TRoot): HttpMessage { fun add(@RequestBody entity: TRoot): HttpMessage {
return this.httpMessageFactory.create(service.add(entity)) val id = service.add(entity)
return this.httpMessageFactory.create(id!!)
} }
@PutMapping("/{id:.+}") @PutMapping("/{id:.+}")

View File

@@ -2,7 +2,7 @@ package com.synebula.gaea.app.controller.cmd
import com.synebula.gaea.data.message.HttpMessageFactory import com.synebula.gaea.data.message.HttpMessageFactory
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.service.ISimpleService import com.synebula.gaea.record.service.IService
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
@@ -15,7 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired
*/ */
open class SimpleCommandApp<TRoot : IAggregateRoot<ID>, ID>( open class SimpleCommandApp<TRoot : IAggregateRoot<ID>, ID>(
override var name: String, override var name: String,
override var service: ISimpleService<TRoot, ID>, override var service: IService<TRoot, ID>,
override var logger: ILogger, override var logger: ILogger,
) : ISimpleCommandApp<TRoot, ID> { ) : ISimpleCommandApp<TRoot, ID> {
@Autowired @Autowired

View File

@@ -2,8 +2,8 @@ package com.synebula.gaea.app.controller.query
import com.synebula.gaea.app.controller.IApplication import com.synebula.gaea.app.controller.IApplication
import com.synebula.gaea.data.message.HttpMessage import com.synebula.gaea.data.message.HttpMessage
import com.synebula.gaea.query.IQuery import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.query.Params import com.synebula.gaea.db.query.Params
import com.synebula.gaea.spring.aop.annotation.Method import com.synebula.gaea.spring.aop.annotation.Method
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PathVariable

View File

@@ -1,8 +1,8 @@
package com.synebula.gaea.app.controller.query package com.synebula.gaea.app.controller.query
import com.synebula.gaea.data.message.HttpMessageFactory import com.synebula.gaea.data.message.HttpMessageFactory
import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
import com.synebula.gaea.query.IQuery
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
/** /**

View File

@@ -1,8 +1,8 @@
package com.synebula.gaea.jpa package com.synebula.gaea.jpa
import com.synebula.gaea.query.IQuery import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.query.Page import com.synebula.gaea.db.query.Page
import com.synebula.gaea.query.Params import com.synebula.gaea.db.query.Params
import jakarta.persistence.EntityManager import jakarta.persistence.EntityManager
import org.springframework.data.jpa.repository.support.SimpleJpaRepository import org.springframework.data.jpa.repository.support.SimpleJpaRepository
@@ -14,7 +14,7 @@ class JpaQuery<TView, ID>(override var clazz: Class<TView>, entityManager: Entit
} }
override operator fun get(id: ID): TView? { override operator fun get(id: ID): TView? {
val view = this.repo.findById(id) val view = this.repo.findById(id!!)
return if (view.isPresent) view.get() else null return if (view.isPresent) view.get() else null
} }

View File

@@ -1,8 +1,8 @@
package com.synebula.gaea.jpa package com.synebula.gaea.jpa
import com.synebula.gaea.data.date.DateTime import com.synebula.gaea.data.date.DateTime
import com.synebula.gaea.query.Operator import com.synebula.gaea.db.query.Operator
import com.synebula.gaea.query.Where import com.synebula.gaea.db.query.Where
import jakarta.persistence.criteria.* import jakarta.persistence.criteria.*
import org.springframework.data.jpa.domain.Specification import org.springframework.data.jpa.domain.Specification
import java.lang.reflect.Field import java.lang.reflect.Field

View File

@@ -5,13 +5,13 @@ import org.springframework.beans.factory.FactoryBean
import org.springframework.cglib.proxy.Enhancer import org.springframework.cglib.proxy.Enhancer
import org.springframework.data.repository.Repository import org.springframework.data.repository.Repository
class JpaRepositoryFactory( class JpaDbContextFactory(
private val beanFactory: BeanFactory, private val beanFactory: BeanFactory,
private val interfaceType: Class<*>, private val interfaceType: Class<*>,
private val implBeanNames: List<String> private val implBeanNames: List<String>
) : FactoryBean<Any> { ) : FactoryBean<Any> {
override fun getObject(): Any { override fun getObject(): Any {
val handler: JpaRepositoryProxy<*, *, *> = JpaRepositoryProxy<Repository<Any, Any>, Any, Any>( val handler: JpaDbContextProxy<*, *, *> = JpaDbContextProxy<Repository<Any, Any>, Any, Any>(
beanFactory, beanFactory,
interfaceType, implBeanNames interfaceType, implBeanNames
) )

View File

@@ -26,7 +26,7 @@ import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type import java.lang.reflect.Type
class JpaRepositoryProxy<T : Repository<S, ID>?, S, ID>( class JpaDbContextProxy<T : Repository<S, ID>?, S, ID>(
beanFactory: BeanFactory, beanFactory: BeanFactory,
interfaceType: Class<*>, interfaceType: Class<*>,
implementBeanNames: List<String>? implementBeanNames: List<String>?

View File

@@ -8,5 +8,5 @@ import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented @MustBeDocumented
@Inherited @Inherited
@Import(JpaRepositoryRegister::class) @Import(JpaDbContextRegister::class)
annotation class JpaRepositoryProxyScan(val basePackages: Array<String> = [], val scanInterfaces: Array<KClass<*>> = []) annotation class JpaDbContextProxyScan(val basePackages: Array<String> = [], val scanInterfaces: Array<KClass<*>> = [])

View File

@@ -24,17 +24,20 @@ import org.springframework.util.ClassUtils
import java.util.* import java.util.*
import java.util.stream.Collectors import java.util.stream.Collectors
class JpaRepositoryRegister : ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware, class JpaDbContextRegister : ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware,
EnvironmentAware, EnvironmentAware,
BeanFactoryAware { BeanFactoryAware {
private lateinit var environment: Environment private lateinit var environment: Environment
private lateinit var resourceLoader: ResourceLoader private lateinit var resourceLoader: ResourceLoader
private var classLoader: ClassLoader? = null private var classLoader: ClassLoader? = null
private var beanFactory: BeanFactory? = null private var beanFactory: BeanFactory? = null
override fun registerBeanDefinitions(metadata: AnnotationMetadata, registry: BeanDefinitionRegistry) { override fun registerBeanDefinitions(metadata: AnnotationMetadata, registry: BeanDefinitionRegistry) {
val attributes = AnnotationAttributes( val attributes = AnnotationAttributes(
metadata.getAnnotationAttributes( metadata.getAnnotationAttributes(
JpaRepositoryProxyScan::class.java.name JpaDbContextProxyScan::class.java.name
) ?: mapOf() ) ?: mapOf()
) )
val basePackages = attributes.getStringArray("basePackages") val basePackages = attributes.getStringArray("basePackages")
@@ -55,7 +58,7 @@ class JpaRepositoryRegister : ImportBeanDefinitionRegistrar, ResourceLoaderAware
val implClazzDefinitions = scan(basePackages, arrayOf(beanClazzTypeFilter)) val implClazzDefinitions = scan(basePackages, arrayOf(beanClazzTypeFilter))
for (definition in implClazzDefinitions) { for (definition in implClazzDefinitions) {
definition.isAutowireCandidate = false definition.isAutowireCandidate = false
registry.registerBeanDefinition(Objects.requireNonNull(definition.beanClassName), definition) registry.registerBeanDefinition(Objects.requireNonNull(definition.beanClassName!!), definition)
} }
// 构建bean定义 // 构建bean定义
// 1 bean参数 // 1 bean参数
@@ -66,7 +69,7 @@ class JpaRepositoryRegister : ImportBeanDefinitionRegistrar, ResourceLoaderAware
builder.addConstructorArgValue(beanClazz) builder.addConstructorArgValue(beanClazz)
builder.addConstructorArgValue(implBeanNames) builder.addConstructorArgValue(implBeanNames)
val definition = builder.rawBeanDefinition as GenericBeanDefinition val definition = builder.rawBeanDefinition as GenericBeanDefinition
definition.beanClass = JpaRepositoryFactory::class.java definition.beanClass = JpaDbContextFactory::class.java
definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE
registry.registerBeanDefinition(beanClazz.name, definition) registry.registerBeanDefinition(beanClazz.name, definition)
} }

View File

@@ -5,7 +5,7 @@ import com.synebula.gaea.jpa.proxy.method.resolver.AbstractMethodResolver
import com.synebula.gaea.jpa.proxy.method.resolver.DefaultMethodResolver import com.synebula.gaea.jpa.proxy.method.resolver.DefaultMethodResolver
import com.synebula.gaea.jpa.proxy.method.resolver.FindMethodResolver import com.synebula.gaea.jpa.proxy.method.resolver.FindMethodResolver
import com.synebula.gaea.jpa.proxy.method.resolver.PageMethodResolver import com.synebula.gaea.jpa.proxy.method.resolver.PageMethodResolver
import com.synebula.gaea.query.Params import com.synebula.gaea.db.query.Params
import org.springframework.data.domain.Pageable import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.domain.Specification import org.springframework.data.jpa.domain.Specification
import java.lang.reflect.InvocationTargetException import java.lang.reflect.InvocationTargetException

View File

@@ -1,8 +1,8 @@
package com.synebula.gaea.jpa.proxy.method.resolver package com.synebula.gaea.jpa.proxy.method.resolver
import com.synebula.gaea.jpa.toSpecification import com.synebula.gaea.jpa.toSpecification
import com.synebula.gaea.query.Order import com.synebula.gaea.db.query.Order
import com.synebula.gaea.query.Params import com.synebula.gaea.db.query.Params
import jakarta.persistence.EmbeddedId import jakarta.persistence.EmbeddedId
import jakarta.persistence.Id import jakarta.persistence.Id
import org.springframework.data.domain.Page import org.springframework.data.domain.Page
@@ -10,7 +10,7 @@ import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort import org.springframework.data.domain.Sort
import java.util.* import java.util.*
import com.synebula.gaea.query.Page as QueryPage import com.synebula.gaea.db.query.Page as QueryPage
/** /**
* 分页方法参数映射 * 分页方法参数映射

View File

@@ -1,9 +1,9 @@
package com.synebula.gaea.mongodb package com.synebula.gaea.mongodb
import com.synebula.gaea.data.date.DateTime import com.synebula.gaea.data.date.DateTime
import com.synebula.gaea.query.Operator import com.synebula.gaea.db.query.Operator
import com.synebula.gaea.query.Order import com.synebula.gaea.db.query.Order
import com.synebula.gaea.query.Where import com.synebula.gaea.db.query.Where
import org.springframework.data.domain.Sort import org.springframework.data.domain.Sort
import org.springframework.data.mongodb.core.query.Criteria import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query import org.springframework.data.mongodb.core.query.Query

View File

@@ -4,11 +4,11 @@ import com.synebula.gaea.spring.autoconfig.Factory
import com.synebula.gaea.spring.autoconfig.Proxy import com.synebula.gaea.spring.autoconfig.Proxy
import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.BeanFactory
class MongodbRepositoryFactory( class MongoDbContextFactory(
supertype: Class<*>, supertype: Class<*>,
var beanFactory: BeanFactory, var beanFactory: BeanFactory,
) : Factory(supertype) { ) : Factory(supertype) {
override fun createProxy(): Proxy { override fun createProxy(): Proxy {
return MongodbRepositoryProxy(supertype, this.beanFactory) return MongoDbContextProxy(supertype, this.beanFactory)
} }
} }

View File

@@ -0,0 +1,69 @@
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.repository.MongodbRepository
import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.reflect.getGenericInterface
import com.synebula.gaea.spring.autoconfig.Proxy
import org.springframework.beans.factory.BeanFactory
import org.springframework.data.mongodb.core.MongoTemplate
import java.lang.reflect.Method
class MongoDbContextProxy(
private var supertype: Class<*>, private var beanFactory: BeanFactory
) : Proxy() {
/**
* 实际的执行类
*/
private var context: Any?
init {
if (this.supertype.interfaces.any { it == IDbContext::class.java }) {
this.context = beanFactory.getBean(IDbContext::class.java)
if (context == null) {
val constructor = IDbContext::class.java.getConstructor(Class::class.java, MongoTemplate::class.java)
this.context = constructor.newInstance(this.beanFactory.getBean(MongoTemplate::class.java))
}
} else {
// 判断接口类型
val clazz: Class<*> // 代理服务类型
val interfaceClazz: Class<*> // 代理服务接口
if (this.supertype.interfaces.any { it == IQuery::class.java }) {
clazz = MongodbQuery::class.java
interfaceClazz = IQuery::class.java
} else {
clazz = MongodbRepository::class.java
interfaceClazz = IRepository::class.java
}
val constructor = clazz.getConstructor(Class::class.java, MongoTemplate::class.java)
this.context = constructor.newInstance(
this.supertype.getGenericInterface(interfaceClazz)!!.actualTypeArguments[0],
this.beanFactory.getBean(MongoTemplate::class.java)
)
}
}
/**
* 执行代理方法
*
* @param proxy 代理对象
* @param method 需要执行的方法
* @param args 参数列表
* @return 方法执行结果
*/
override fun exec(proxy: Any, method: Method, args: Array<Any>): Any? {
try {
val proxyMethod: Method = this.context!!.javaClass.getMethod(method.name, *method.parameterTypes)
return proxyMethod.invoke(this.context, *args)
} catch (ex: NoSuchMethodException) {
throw NoSuchMethodException("method [${method.toGenericString()}] not implements in class [${this.context!!.javaClass}], you must implements interface [${this.supertype.name}] ")
}
}
}

View File

@@ -1,7 +1,8 @@
package com.synebula.gaea.mongodb.autoconfig package com.synebula.gaea.mongodb.autoconfig
import com.synebula.gaea.db.context.IDbContext
import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.domain.repository.IRepository import com.synebula.gaea.domain.repository.IRepository
import com.synebula.gaea.query.IQuery
import com.synebula.gaea.spring.autoconfig.Register import com.synebula.gaea.spring.autoconfig.Register
import org.springframework.beans.factory.config.BeanDefinition import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.support.BeanDefinitionBuilder import org.springframework.beans.factory.support.BeanDefinitionBuilder
@@ -9,20 +10,20 @@ import org.springframework.beans.factory.support.GenericBeanDefinition
import org.springframework.core.annotation.AnnotationAttributes import org.springframework.core.annotation.AnnotationAttributes
import org.springframework.core.type.AnnotationMetadata import org.springframework.core.type.AnnotationMetadata
class MongodbRepositoryRegister : Register() { class MongoDbContextRegister : Register() {
override fun scan(metadata: AnnotationMetadata): Map<String, BeanDefinition> { override fun scan(metadata: AnnotationMetadata): Map<String, BeanDefinition> {
val result = mutableMapOf<String, BeanDefinition>() val result = mutableMapOf<String, BeanDefinition>()
// 获取注解参数信息:basePackages // 获取注解参数信息:basePackages
val attributes = AnnotationAttributes( val attributes = AnnotationAttributes(
metadata.getAnnotationAttributes( metadata.getAnnotationAttributes(
MongodbRepositoryScan::class.java.name MongoDbRepositoryScan::class.java.name
) ?: mapOf() ) ?: mapOf()
) )
val basePackages = attributes.getStringArray("basePackages") val basePackages = attributes.getStringArray("basePackages")
val beanDefinitions = this.doScan( val beanDefinitions = this.doScan(
basePackages, basePackages,
arrayOf(this.interfaceFilter(arrayOf(IRepository::class.java, IQuery::class.java))) arrayOf(this.interfaceFilter(arrayOf(IDbContext::class.java, IQuery::class.java, IRepository::class.java)))
) )
beanDefinitions.forEach { beanDefinition -> beanDefinitions.forEach { beanDefinition ->
// 获取实际的bean类型 // 获取实际的bean类型
@@ -44,7 +45,7 @@ class MongodbRepositoryRegister : Register() {
builder.addConstructorArgValue(beanClazz) builder.addConstructorArgValue(beanClazz)
builder.addConstructorArgValue(this._beanFactory) builder.addConstructorArgValue(this._beanFactory)
val definition = builder.rawBeanDefinition as GenericBeanDefinition val definition = builder.rawBeanDefinition as GenericBeanDefinition
definition.beanClass = MongodbRepositoryFactory::class.java definition.beanClass = MongoDbContextFactory::class.java
definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE
result[beanClazz.name] = definition result[beanClazz.name] = definition
} }
@@ -59,7 +60,7 @@ class MongodbRepositoryRegister : Register() {
builder.addConstructorArgValue(this._beanFactory) builder.addConstructorArgValue(this._beanFactory)
builder.addConstructorArgValue(emptyArray<String>()) builder.addConstructorArgValue(emptyArray<String>())
val definition = builder.rawBeanDefinition as GenericBeanDefinition val definition = builder.rawBeanDefinition as GenericBeanDefinition
definition.beanClass = MongodbRepositoryFactory::class.java definition.beanClass = MongoDbContextFactory::class.java
definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE definition.autowireMode = GenericBeanDefinition.AUTOWIRE_BY_TYPE
result[IRepository::class.java.name] = definition result[IRepository::class.java.name] = definition
} }

View File

@@ -8,5 +8,5 @@ import java.lang.annotation.Inherited
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented @MustBeDocumented
@Inherited @Inherited
@Import(MongodbRepositoryRegister::class) @Import(MongoDbContextRegister::class)
annotation class MongodbRepositoryScan(val basePackages: Array<String> = []) annotation class MongoDbRepositoryScan(val basePackages: Array<String> = [])

View File

@@ -1,55 +0,0 @@
package com.synebula.gaea.mongodb.autoconfig
import com.synebula.gaea.domain.repository.IRepository
import com.synebula.gaea.mongodb.query.MongodbQuery
import com.synebula.gaea.mongodb.repository.MongodbRepository
import com.synebula.gaea.query.IQuery
import com.synebula.gaea.reflect.getGenericInterface
import com.synebula.gaea.spring.autoconfig.Proxy
import org.springframework.beans.factory.BeanFactory
import org.springframework.data.mongodb.core.MongoTemplate
import java.lang.reflect.Method
class MongodbRepositoryProxy(
private var supertype: Class<*>, private var beanFactory: BeanFactory
) : Proxy() {
private var mongodbRepo: Any
init {
// 判断接口类型
val clazz: Class<*> // 代理服务类型
val interfaceClazz: Class<*> // 代理服务接口
if (this.supertype.interfaces.any { it == IRepository::class.java }) {
clazz = MongodbRepository::class.java
interfaceClazz = IRepository::class.java
} else {
clazz = MongodbQuery::class.java
interfaceClazz = IQuery::class.java
}
val constructor = clazz.getConstructor(Class::class.java, MongoTemplate::class.java)
this.mongodbRepo = constructor.newInstance(
this.supertype.getGenericInterface(interfaceClazz)!!.actualTypeArguments[0],
this.beanFactory.getBean(MongoTemplate::class.java)
)
}
/**
* 执行代理方法
*
* @param proxy 代理对象
* @param method 需要执行的方法
* @param args 参数列表
* @return 方法执行结果
*/
override fun exec(proxy: Any, method: Method, args: Array<Any>): Any? {
try {
val proxyMethod: Method = this.mongodbRepo.javaClass.getMethod(method.name, *method.parameterTypes)
return proxyMethod.invoke(this.mongodbRepo, *args)
} catch (ex: NoSuchMethodException) {
throw NoSuchMethodException("method [${method.toGenericString()}] not implements in class [${this.mongodbRepo.javaClass}], you must implements interface [${this.supertype.name}] ")
}
}
}

View File

@@ -0,0 +1,50 @@
package com.synebula.gaea.mongodb.db.context
import com.synebula.gaea.db.IEntity
import com.synebula.gaea.db.context.IDbContext
import com.synebula.gaea.mongodb.where
import com.synebula.gaea.mongodb.whereId
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Query
class MongodbContext(
protected var template: MongoTemplate
) : IDbContext {
override fun <TEntity : IEntity<ID>, ID> add(entity: TEntity, clazz: Class<TEntity>) {
this.template.save(entity)
}
override fun <TEntity : IEntity<ID>, ID> add(entities: List<TEntity>, clazz: Class<TEntity>) {
this.template.insert(entities, clazz)
}
override fun <TEntity : IEntity<ID>, ID> remove(id: ID, clazz: Class<TEntity>) {
this.template.remove(whereId(id), clazz)
}
override fun <TEntity : IEntity<ID>, ID> get(id: ID, clazz: Class<TEntity>): TEntity? {
return this.template.findOne(whereId(id), clazz)
}
override fun <TEntity : IEntity<ID>, ID> update(entity: TEntity, clazz: Class<TEntity>) {
this.template.save(entity)
}
override fun <TEntity : IEntity<ID>, ID> update(entities: List<TEntity>, clazz: Class<TEntity>) {
this.template.save(entities)
}
override fun <TEntity : IEntity<ID>, ID> count(params: Map<String, String>?, clazz: Class<TEntity>): Int {
val query = Query()
return this.template.count(query.where(params, clazz), clazz).toInt()
}
override val isCommitted=true
override fun commit() {
}
override fun rollback() {
}
}

View File

@@ -1,24 +1,20 @@
package com.synebula.gaea.mongodb.query package com.synebula.gaea.mongodb.db.query
import com.synebula.gaea.ext.firstCharLowerCase import com.synebula.gaea.ext.firstCharLowerCase
import com.synebula.gaea.mongodb.order import com.synebula.gaea.mongodb.order
import com.synebula.gaea.mongodb.select import com.synebula.gaea.mongodb.select
import com.synebula.gaea.mongodb.where import com.synebula.gaea.mongodb.where
import com.synebula.gaea.mongodb.whereId import com.synebula.gaea.mongodb.whereId
import com.synebula.gaea.query.IQuery import com.synebula.gaea.db.query.IQuery
import com.synebula.gaea.query.Page import com.synebula.gaea.db.query.Page
import com.synebula.gaea.query.Params import com.synebula.gaea.db.query.Params
import com.synebula.gaea.query.Table import com.synebula.gaea.db.query.Table
import com.synebula.gaea.reflect.fieldNames import com.synebula.gaea.reflect.fieldNames
import org.springframework.data.mongodb.core.MongoTemplate import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query import org.springframework.data.mongodb.core.query.Query
/**
* 实现IQuery的Mongodb查询类
* @param template MongodbRepo对象
*/
open class MongodbQuery<TView, ID>(override var clazz: Class<TView>, var template: MongoTemplate) : open class MongodbQuery<TView, ID>(override var clazz: Class<TView>, var template: MongoTemplate) :
IQuery<TView, ID> { IQuery<TView, ID> {

View File

@@ -1,23 +0,0 @@
package com.synebula.gaea.mongodb.query
import com.synebula.gaea.query.IQuery
import com.synebula.gaea.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

@@ -1,88 +0,0 @@
package com.synebula.gaea.mongodb.query
import com.synebula.gaea.ext.firstCharLowerCase
import com.synebula.gaea.mongodb.order
import com.synebula.gaea.mongodb.select
import com.synebula.gaea.mongodb.where
import com.synebula.gaea.mongodb.whereId
import com.synebula.gaea.query.IUniversalQuery
import com.synebula.gaea.query.Page
import com.synebula.gaea.query.Params
import com.synebula.gaea.query.Table
import com.synebula.gaea.reflect.fieldNames
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
/**
* 实现IQuery的Mongodb查询类
* @param template MongodbRepo对象
*/
open class MongodbUniversalQuery(var template: MongoTemplate) : IUniversalQuery {
/**
* 使用View解析是collection时是否校验存在默认不校验
*/
var validViewCollection = false
override fun <TView, ID> get(id: ID, clazz: Class<TView>): TView? {
return this.template.findOne(whereId(id), clazz, this.collection(clazz))
}
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)
query.select(fields)
return this.find(query, clazz)
}
override fun <TView> count(params: Map<String, String>?, clazz: Class<TView>): Int {
val query = Query()
return this.template.count(query.where(params, clazz), this.collection(clazz)).toInt()
}
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, clazz)
//如果总数和索引相同,说明该页没有数据,直接跳到上一页
if (result.total == result.index) {
params.page -= 1
result.page -= 1
}
query.select(fields)
query.where(params.parameters, clazz)
query.with(order(params.orders))
query.skip(params.index).limit(params.size)
result.data = this.find(query, clazz)
return result
}
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 <TView> find(query: Query, clazz: Class<TView>): List<TView> {
return this.template.find(query, clazz, this.collection(clazz))
}
fun <TView> fields(clazz: Class<TView>): Array<String> {
return clazz.fieldNames().toTypedArray()
}
/**
* 获取collection
*/
fun <TView> collection(clazz: Class<TView>): String {
val table = clazz.getDeclaredAnnotation(Table::class.java)
return if (table != null) table.name
else {
val name = clazz.simpleName.removeSuffix("View").firstCharLowerCase()
if (!validViewCollection || this.template.collectionExists(name)) name
else throw RuntimeException("找不到名为[${clazz.name}]的集合")
}
}
}

View File

@@ -1,61 +0,0 @@
package com.synebula.gaea.mongodb.repository
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IUniversalRepository
import com.synebula.gaea.mongodb.where
import com.synebula.gaea.mongodb.whereId
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Query
/**
* 实现ITypedRepository的Mongodb仓储类
* @param repo MongodbRepo对象
*/
open class MongodbUniversalRepository(private var repo: MongoTemplate) : IUniversalRepository {
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> remove(id: ID, clazz: Class<TAggregateRoot>) {
this.repo.remove(whereId(id), clazz)
}
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> get(
id: ID,
clazz: Class<TAggregateRoot>,
): TAggregateRoot? {
return this.repo.findOne(whereId(id), clazz)
}
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> update(
root: TAggregateRoot,
clazz: Class<TAggregateRoot>,
) {
this.repo.save(root)
}
/**
* 更新多个个对象。
*
* @param roots 需要更新的对象。
*/
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> update(
roots: List<TAggregateRoot>,
clazz: Class<TAggregateRoot>
) {
this.repo.save(roots)
}
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> add(root: TAggregateRoot, clazz: Class<TAggregateRoot>) {
this.repo.save(root)
}
override fun <TAggregateRoot : IAggregateRoot<ID>, ID> add(
roots: List<TAggregateRoot>,
clazz: Class<TAggregateRoot>,
) {
this.repo.insert(roots, clazz)
}
override fun <TAggregateRoot> count(params: Map<String, String>?, clazz: Class<TAggregateRoot>): Int {
val query = Query()
return this.repo.count(query.where(params, clazz), clazz).toInt()
}
}

View File

@@ -5,7 +5,6 @@ import com.synebula.gaea.data.serialization.json.IJsonSerializer
class HttpMessage(private var serializer: IJsonSerializer) : DataMessage<Any>() { class HttpMessage(private var serializer: IJsonSerializer) : DataMessage<Any>() {
constructor(data: Any, serializer: IJsonSerializer) : this(serializer) { constructor(data: Any, serializer: IJsonSerializer) : this(serializer) {
this.data = data this.data = data
} }

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.domain.model package com.synebula.gaea.db
/** /**
* 继承本接口说明对象为实体类型 * 继承本接口说明对象为实体类型

View File

@@ -0,0 +1,66 @@
package com.synebula.gaea.db.context
import com.synebula.gaea.db.IEntity
/**
* 继承自IUnitOfWork表示实现了工作单元模式的上下文接口。
*
* @author alex
*/
interface IDbContext : IUnitOfWork {
/**
* 插入单个对象。
*
* @param entity 需要插入的对象。
* @return 返回原对象如果对象ID为自增则补充自增ID。
*/
fun <TEntity : IEntity<ID>, ID> add(entity: TEntity, clazz: Class<TEntity>)
/**
* 插入多个个对象。
*
* @param entities 需要插入的对象。
*/
fun <TEntity : IEntity<ID>, ID> add(entities: List<TEntity>, clazz: Class<TEntity>)
/**
* 更新对象。
*
* @param entity 需要更新的对象。
* @return
*/
fun <TEntity : IEntity<ID>, ID> update(entity: TEntity, clazz: Class<TEntity>)
/**
* 更新多个个对象。
*
* @param entities 需要更新的对象。
*/
fun <TEntity : IEntity<ID>, ID> update(entities: List<TEntity>, clazz: Class<TEntity>)
/**
* 通过id删除该条数据
*
* @param id id
* @param clazz 操作数据的类型
*/
fun <TEntity : IEntity<ID>, ID> remove(id: ID, clazz: Class<TEntity>)
/**
* 根据ID获取对象。
*
* @param id id
* @param clazz 操作数据的类型
* @return 聚合根
*/
fun <TEntity : IEntity<ID>, ID> get(id: ID, clazz: Class<TEntity>): TEntity?
/**
* 根据条件查询符合条件记录的数量
*
* @param params 查询条件。
* @return int
*/
fun <TEntity : IEntity<ID>, ID> count(params: Map<String, String>?, clazz: Class<TEntity>): Int
}

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.domain.repository.context package com.synebula.gaea.db.context
/** /**
* 表示所有继承于该接口的类型都是Unit Of Work的一种实现 * 表示所有继承于该接口的类型都是Unit Of Work的一种实现

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
/** /**
* 查询基接口, 其中方法都指定了查询的视图类型 * 查询基接口, 其中方法都指定了查询的视图类型

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
enum class Operator { enum class Operator {
/** /**

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
/** /**
* class OrderType * class OrderType

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
/** /**
* 分页数据 * 分页数据

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
/** /**
* class 分页参数信息 * class 分页参数信息

View File

@@ -1,3 +1,3 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
annotation class Table(val name: String = "") annotation class Table(val name: String = "")

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.query package com.synebula.gaea.db.query
/** /**
* 字段注解规定字段的查询方式 * 字段注解规定字段的查询方式

View File

@@ -1,6 +1,6 @@
package com.synebula.gaea.domain.event package com.synebula.gaea.domain.event
import com.synebula.gaea.data.message.IEvent import com.synebula.gaea.data.message.IEvent
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.db.IEntity
class AfterRemoveEvent<T : IAggregateRoot<I>, I>(var id: I? = null) : IEvent class AfterRemoveEvent<T : IEntity<I>, I>(var id: I? = null) : IEvent

View File

@@ -1,6 +1,7 @@
package com.synebula.gaea.domain.event package com.synebula.gaea.domain.event
import com.synebula.gaea.data.message.IEvent import com.synebula.gaea.data.message.IEvent
import com.synebula.gaea.db.IEntity
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.domain.model.IAggregateRoot
class BeforeRemoveEvent<T : IAggregateRoot<I>, I>(var id: I? = null) : IEvent class BeforeRemoveEvent<T : IEntity<I>, I>(var id: I? = null) : IEvent

View File

@@ -1,5 +1,5 @@
package com.synebula.gaea.domain.model package com.synebula.gaea.domain.model
abstract class AggregateRoot<ID> : Entity<ID>(), IAggregateRoot<ID> { abstract class AggregateRoot<ID> : Entity<ID>(), IAggregateRoot<ID> {
override var alive: Boolean = true override var avalible: Boolean = true
} }

View File

@@ -1,3 +1,5 @@
package com.synebula.gaea.domain.model package com.synebula.gaea.domain.model
import com.synebula.gaea.db.IEntity
abstract class Entity<ID> : IEntity<ID> abstract class Entity<ID> : IEntity<ID>

View File

@@ -1,5 +1,7 @@
package com.synebula.gaea.domain.model package com.synebula.gaea.domain.model
import com.synebula.gaea.db.IEntity
/** /**
* 继承本接口,说明对象为聚合根。 * 继承本接口,说明对象为聚合根。
* *
@@ -10,5 +12,5 @@ interface IAggregateRoot<ID> : IEntity<ID> {
/** /**
* 实体对象是否有效。 * 实体对象是否有效。
*/ */
var alive: Boolean var avalible: Boolean
} }

View File

@@ -1,7 +0,0 @@
package com.synebula.gaea.domain.model
/**
* 继承本接口,说明对象为值类型。
* @author alex
*/
interface IValue

View File

@@ -1,65 +0,0 @@
package com.synebula.gaea.domain.repository
import com.synebula.gaea.domain.model.IAggregateRoot
/**
* 定义了提供增删改的仓储接口。
* 本接口泛型放置到方法上并需要显式提供聚合根的class对象
*/
interface IUniversalRepository {
/**
* 插入单个对象。
*
* @param root 需要插入的对象。
* @return 返回原对象如果对象ID为自增则补充自增ID。
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> add(root: TAggregateRoot, clazz: Class<TAggregateRoot>)
/**
* 插入多个个对象。
*
* @param roots 需要插入的对象。
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> add(roots: List<TAggregateRoot>, clazz: Class<TAggregateRoot>)
/**
* 更新对象。
*
* @param root 需要更新的对象。
* @return
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> update(root: TAggregateRoot, clazz: Class<TAggregateRoot>)
/**
* 更新多个个对象。
*
* @param roots 需要更新的对象。
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> update(roots: List<TAggregateRoot>, clazz: Class<TAggregateRoot>)
/**
* 通过id删除该条数据
*
* @param id id
* @param clazz 操作数据的类型
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> remove(id: ID, clazz: Class<TAggregateRoot>)
/**
* 根据ID获取对象。
*
* @param id id
* @param clazz 操作数据的类型
* @return 聚合根
*/
fun <TAggregateRoot : IAggregateRoot<ID>, ID> get(id: ID, clazz: Class<TAggregateRoot>): TAggregateRoot?
/**
* 根据条件查询符合条件记录的数量
*
* @param params 查询条件。
* @return int
*/
fun <TAggregateRoot> count(params: Map<String, String>?, clazz: Class<TAggregateRoot>): Int
}

View File

@@ -1,30 +0,0 @@
package com.synebula.gaea.domain.repository.context
import com.synebula.gaea.domain.model.IAggregateRoot
/**
* 继承自IUnitOfWork表示实现了工作单元模式的上下文接口。
*
* @author alex
*/
interface IContext : IUnitOfWork {
/**
* 将指定的聚合根标注为“新建”状态。
* @param obj 聚合根
*/
fun <T : IAggregateRoot<ID>, ID> add(obj: T)
/**
* 将指定的聚合根标注为“更改”状态。
*
* @param obj 聚合根
*/
fun <T : IAggregateRoot<ID>, ID> update(obj: T)
/**
* 将指定的聚合根标注为“删除”状态。
*
* @param obj 聚合根
*/
fun <T : IAggregateRoot<ID>, ID> remove(obj: T)
}

View File

@@ -1,67 +0,0 @@
package com.synebula.gaea.domain.service
import com.synebula.gaea.bus.IBus
import com.synebula.gaea.data.message.DataMessage
import com.synebula.gaea.domain.event.AfterRemoveEvent
import com.synebula.gaea.domain.event.BeforeRemoveEvent
import com.synebula.gaea.domain.model.IAggregateRoot
import com.synebula.gaea.domain.repository.IRepository
import com.synebula.gaea.log.ILogger
/**
* 依赖了IRepository仓储借口的服务实现类 GenericsService
* 该类依赖仓储接口 @see IGenericsRepository, 需要显式提供聚合根的class对象
*
* @param repository 仓储对象
* @param clazz 聚合根类对象
* @param logger 日志组件
* @author alex
* @version 0.1
* @since 2020-05-17
*/
open class SimpleService<TRoot : IAggregateRoot<ID>, ID>(
protected open var clazz: Class<TRoot>,
protected open var repository: IRepository<TRoot, ID>,
override var logger: ILogger,
protected open var bus: IBus<Any>? = null
) : ISimpleService<TRoot, ID> {
override fun add(root: TRoot): DataMessage<ID> {
val msg = DataMessage<ID>()
this.repository.add(root)
msg.data = root.id
return msg
}
override fun update(id: ID, root: TRoot) {
root.id = id
this.repository.update(root)
}
override fun remove(id: ID) {
val beforeRemoveEvent = BeforeRemoveEvent<TRoot, ID>(id)
this.bus?.publish(beforeRemoveEvent.topic(this.clazz), beforeRemoveEvent)
this.repository.remove(id)
val afterRemoveEvent = AfterRemoveEvent<TRoot, ID>(id)
this.bus?.publish(afterRemoveEvent.topic(this.clazz), afterRemoveEvent)
}
/**
* 增加对象
*
* @param roots 增加对象命令列表
*/
override fun add(roots: List<TRoot>) {
this.repository.add(roots)
}
/**
* 批量更新对象
*
* @param roots 更新对象命令列表
*/
override fun update(roots: List<TRoot>) {
this.repository.update(roots)
}
}

View File

@@ -1,18 +0,0 @@
package com.synebula.gaea.query
/**
* Query 工厂接口。 定义了Query的创建方法。
*/
interface IQueryFactory {
/**
* 创建原始类型的IQuery接口类型
*/
fun createRawQuery(clazz: Class<*>): IQuery<*, *>
/**
* 创建指定类型的IQuery接口类型
*/
fun <T, I> createQuery(clazz: Class<T>): IQuery<T, I>
}

View File

@@ -1,49 +0,0 @@
package com.synebula.gaea.query
/**
* 查询基接口, 其中方法都指定了查询的视图类型。
*
* @author alex
*/
interface IUniversalQuery {
/**
* 根据Key获取对象。
*
* @param id 对象Key。
* @return 视图结果
*/
fun <TView, ID> get(id: ID, clazz: Class<TView>): TView?
/**
* 根据实体类条件查询所有符合条件记录
*
* @param params 查询条件。
* @return 视图列表
*/
fun <TView> list(params: Map<String, String>?, clazz: Class<TView>): List<TView>
/**
* 根据条件查询符合条件记录的数量
*
* @param params 查询条件。
* @return 数量
*/
fun <TView> count(params: Map<String, String>?, clazz: Class<TView>): Int
/**
* 根据实体类条件查询所有符合条件记录(分页查询)
*
* @param params 分页条件
* @return 分页数据
*/
fun <TView> paging(params: Params, clazz: Class<TView>): Page<TView>
/**
* 查询条件范围内数据。
* @param field 查询字段
* @param params 查询条件
*
* @return 视图列表
*/
fun <TView> range(field: String, params: List<Any>, clazz: Class<TView>): List<TView>
}

View File

@@ -0,0 +1,5 @@
package com.synebula.gaea.record.model
import com.synebula.gaea.db.IEntity
interface IRecord<ID> : IEntity<ID>

View File

@@ -1,4 +1,4 @@
package com.synebula.gaea.domain.record package com.synebula.gaea.record.model
import java.util.* import java.util.*

View File

@@ -1,7 +1,7 @@
package com.synebula.gaea.domain.service package com.synebula.gaea.record.service
import com.synebula.gaea.data.message.DataMessage import com.synebula.gaea.data.message.DataMessage
import com.synebula.gaea.domain.model.IAggregateRoot import com.synebula.gaea.db.IEntity
import com.synebula.gaea.log.ILogger import com.synebula.gaea.log.ILogger
@@ -11,7 +11,7 @@ import com.synebula.gaea.log.ILogger
* @version 0.0.1 * @version 0.0.1
* @since 2016年9月18日 下午2:23:15 * @since 2016年9月18日 下午2:23:15
*/ */
interface ISimpleService<TAggregateRoot : IAggregateRoot<ID>, ID> { interface IService<Entity : IEntity<ID>, ID> {
/** /**
* 日志组件 * 日志组件
*/ */
@@ -20,31 +20,31 @@ interface ISimpleService<TAggregateRoot : IAggregateRoot<ID>, ID> {
/** /**
* 增加对象 * 增加对象
* *
* @param root 增加对象命令 * @param entity 增加对象命令
*/ */
fun add(root: TAggregateRoot): DataMessage<ID> fun add(entity: Entity): ID?
/** /**
* 增加对象 * 增加对象
* *
* @param roots 增加对象命令列表 * @param entities 增加对象命令列表
*/ */
fun add(roots: List<TAggregateRoot>) fun add(entities: List<Entity>)
/** /**
* 更新对象 * 更新对象
* *
* @param id 对象ID * @param id 对象ID
* @param root 更新对象命令 * @param entity 更新对象命令
*/ */
fun update(id: ID, root: TAggregateRoot) fun update(id: ID, entity: Entity)
/** /**
* 批量更新对象 * 批量更新对象
* *
* @param roots 更新对象命令列表 * @param entities 更新对象命令列表
*/ */
fun update(roots: List<TAggregateRoot>) fun update(entities: List<Entity>)
/** /**
* 增加对象 * 增加对象

View File

@@ -0,0 +1,65 @@
package com.synebula.gaea.record.service
import com.synebula.gaea.bus.IBus
import com.synebula.gaea.data.message.DataMessage
import com.synebula.gaea.db.context.IDbContext
import com.synebula.gaea.domain.event.AfterRemoveEvent
import com.synebula.gaea.domain.event.BeforeRemoveEvent
import com.synebula.gaea.log.ILogger
import com.synebula.gaea.record.model.IRecord
/**
* 依赖了IRepository仓储借口的服务实现类 GenericsService
* 该类依赖仓储接口 @see IGenericsRepository, 需要显式提供聚合根的class对象
*
* @param context 仓储对象
* @param clazz 聚合根类对象
* @param logger 日志组件
* @author alex
* @version 0.1
* @since 2020-05-17
*/
open class Service<TEntity : IRecord<ID>, ID>(
protected open var clazz: Class<TEntity>,
protected open var context: IDbContext,
protected open var bus: IBus<Any>? = null,
override var logger: ILogger
) : IService<TEntity, ID> {
override fun add(entity: TEntity): ID? {
this.context.add(entity, clazz)
return entity.id
}
override fun update(id: ID, entity: TEntity) {
entity.id = id
this.context.update(entity, clazz)
}
override fun remove(id: ID) {
val beforeRemoveEvent = BeforeRemoveEvent<TEntity, ID>(id)
this.bus?.publish(beforeRemoveEvent.topic(this.clazz), beforeRemoveEvent)
this.context.remove(id, clazz)
val afterRemoveEvent = AfterRemoveEvent<TEntity, ID>(id)
this.bus?.publish(afterRemoveEvent.topic(this.clazz), afterRemoveEvent)
}
/**
* 增加对象
*
* @param entitys 增加对象命令列表
*/
override fun add(entitys: List<TEntity>) {
this.context.add(entitys, clazz)
}
/**
* 批量更新对象
*
* @param entitys 更新对象命令列表
*/
override fun update(entitys: List<TEntity>) {
this.context.update(entitys, clazz)
}
}