├── .gitignore ├── README.md ├── cheese-db-core ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── cheese │ └── db │ └── core │ ├── DevBaseConfiguration.java │ ├── DevBaseMapperRegistry.java │ ├── condition │ ├── AbstractAction.java │ ├── AbstractTableAction.java │ ├── Action.java │ ├── Actions.java │ ├── CommonSegmentProvider.java │ ├── load │ │ └── LoadAction.java │ ├── manager │ │ └── DevBaseActionManager.java │ ├── page │ │ ├── DevBasePage.java │ │ ├── IPage.java │ │ └── PageFactory.java │ ├── query │ │ ├── ComparatorKeyValue.java │ │ ├── LikeKeyValue.java │ │ └── RangeKeyValue.java │ └── simple │ │ ├── delete │ │ └── DeleteTableAction.java │ │ ├── insert │ │ └── InsertTableAction.java │ │ ├── query │ │ ├── AbstractQueryAction.java │ │ └── QueryTableAction.java │ │ └── update │ │ └── UpdateTableAction.java │ ├── enums │ ├── ActionType.java │ ├── Comparator.java │ ├── LikeType.java │ └── RangeType.java │ ├── exception │ ├── DevBaseException.java │ ├── ParamNotFountException.java │ ├── ResultWrapperException.java │ ├── StatementNotFoundException.java │ └── UnknownActionTypeException.java │ ├── mapper │ └── DB.java │ ├── props │ ├── DataSourceConfig.java │ └── MybatisConfig.java │ ├── proxy │ ├── DevBaseDBMapperMethod.java │ ├── DevBaseDBMethodSignature.java │ ├── DevBaseDBSqlCommand.java │ ├── DevBaseMapperProxy.java │ └── DevBaseMapperProxyFactory.java │ ├── support │ ├── ConfigurationSupport.java │ └── DevBaseConstant.java │ └── wrapper │ ├── BeanWrapperResult.java │ ├── MapWrapperResult.java │ └── WrapperResult.java ├── cheese-db-rpc └── pom.xml ├── cheese-db-sample ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── cheese │ │ │ └── db │ │ │ └── sample │ │ │ ├── CheeseSampleApplication.java │ │ │ └── service │ │ │ ├── ICommonService.java │ │ │ └── impl │ │ │ └── CommonServiceImpl.java │ └── resources │ │ ├── application.properties │ │ └── config │ │ └── db.setting │ └── test │ └── java │ └── com │ └── cheese │ └── db │ └── sample │ └── test │ └── CheeseApplicationTest.java ├── cheese-db-spring-boot-starter ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cheese │ │ └── db │ │ ├── autoconfigure │ │ ├── DevBaseDBAutoConfiguration.java │ │ ├── DevBaseDbAutoImportSelector.java │ │ └── EnableDevBase.java │ │ ├── enums │ │ └── TransactionEnum.java │ │ └── props │ │ └── DevBaseDBProps.java │ └── resources │ └── META-INF │ └── spring-configuration-metadata.json ├── cheese-db-spring ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── cheese │ └── db │ └── spring │ ├── annotation │ ├── DevBaseMapperRegistrar.java │ ├── DevBaseMappers.java │ └── DevBaseMultiDataSourceTransactional.java │ ├── datasource │ └── DatasourceContext.java │ ├── exception │ └── TransactionException.java │ ├── injector │ ├── DevBaseSqlInjector.java │ ├── DevBaseSqlInjectorProvider.java │ ├── DevBaseStatementFactory.java │ ├── collector │ │ ├── InjectMetaCollector.java │ │ ├── SysSqlConfigInjectMetaCollector.java │ │ ├── TableInjectMetaCollector.java │ │ ├── dialect │ │ │ ├── DialectType.java │ │ │ └── MysqlDialectCollector.java │ │ └── method │ │ │ ├── AbstractMethod.java │ │ │ ├── Delete.java │ │ │ ├── Insert.java │ │ │ ├── Select.java │ │ │ ├── SqlMethod.java │ │ │ └── Update.java │ ├── event │ │ ├── DevBaseSqlInjectListener.java │ │ ├── InjectType.java │ │ ├── SqlInjectEvent.java │ │ └── runtime │ │ │ └── DefaultEventSqlInjector.java │ ├── metadata │ │ ├── InjectMeta.java │ │ ├── TableMeta.java │ │ └── simple │ │ │ ├── DefaultInjectMeta.java │ │ │ └── MysqlTableMeta.java │ └── simple │ │ └── DefaultDevBaseSqlInjectorProvider.java │ ├── mapper │ ├── DevBaseClassPathMapperScanner.java │ ├── DevBaseMapperFactoryBean.java │ └── DevBaseMapperScannerConfigurer.java │ ├── support │ ├── DatasourceContextSupport.java │ ├── DevBaseApplicationContextSupport.java │ ├── DevBaseMapperRegistrySupport.java │ ├── DevBaseSqlSessionDaoSupport.java │ └── DevBaseTableMetaSupport.java │ ├── transaction │ ├── aop │ │ ├── DevBaseAnnotationsTransactionMethodInterceptor.java │ │ └── DevBaseMultiDatasourceTransactionAdvisor.java │ └── aspectj │ │ └── DevBaseMultiDataSourceTransactionalAspect.java │ ├── utils │ └── SqlScriptUtils.java │ └── wrappers │ ├── DevBaseDataSourceTransactionManagers.java │ ├── DevBaseDataSources.java │ ├── DevBaseSqlSessionFactories.java │ ├── DevBaseSqlSessions.java │ └── simple │ ├── DefaultDevBaseDataSourceTransactionManagers.java │ ├── DefaultDevBaseDataSources.java │ ├── DefaultDevBaseSqlSessionFactories.java │ └── DefaultDevBaseSqlSessions.java └── doc └── sql ├── cheese-repository-bus.sql └── cheese-repository-sys.sql /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | 33 | 34 | ### Mac 35 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## cheese-repository -- 以mybatis为核心的多数据源的持久层操作框架 2 | 3 | ### 一、架构组件 4 | #### 单体服务 5 | - cheese-db-core:`完成与mybatis的整合,针对多数据源重新设计代理方法的执行策略;设计条件构建工具` 6 | - cheese-db-rpc: (需要拆分cheese-db-spring功能,提供feign、dubbo, 模仿dubbo写一个netty+zookeeper的rpc方式) 7 | - cheese-db-spring: 8 | - `cheese-db整合spring,完成持久层实例BeanDefinition的定义、初始化以及持久层代理的创建;` 9 | - `多数据源、事务管理器、会话工厂以及会话顶层设计及默认实现;` 10 | - `sql注册机以及相关功能设计;` 11 | - `多数据源事务处理` 12 | - cheese-db-spring-boot-starter:`cheese-db-spring接入springboot,提供可插拔式的组件使用方式` 13 | 14 | #### 微服务(服务提供者和消费者组成,支持多种RPC方式) 15 | - cheese-db-common: `基础common,为服务提供者和服务消费者提供顶层设计,如DevBaseService、DevBaseServiceProvider` 16 | - cheese-db-rpc: `提供参数序列化方式(json、hessian2),支持消费者多种rpc调用方式(feign、dubbo)` 17 | - cheese-db-server-core: `持久层服务提供组件,完成cheese-db持久层数据收集和注册,提供多种服务暴露方式,服务暴露方式要与服务调用方式对应` 18 | - cheese-db-client-core: `持久层服务消费组件,通过rpc组件支持多种服务调用方式,服务调用方式要与服务暴露方式对应` 19 | ### 二、架构图 20 | #### 单体服务架构图 21 | 22 | 23 | #### 微服务架构图 24 | 25 | 26 | ### 三、快速开始 27 | #### 单体服务 28 | 1. 引入maven依赖 29 | ```xml 30 | 31 | com.cheese.db 32 | cheese-db-spring-boot-starter 33 | 1.0.0 34 | 35 | ``` 36 | 2. 运行工程下`doc/script/sql`中的`cheese-repository-sys.sql`和`cheese-repository-bus.sql`,目前sql脚本文件只提供mysql 37 | ```markdown 38 | cheese-repository-sys.sql 导入配置数据库 39 | cheese-repository-bus.sql 导入其他数据库(可以多个业务数据库,这里提供一个demo) 40 | 41 | ``` 42 | 43 | 3. 搭建springboot工程,并在启动类上添加`@EnableDevBase`注解(请参考cheese-db-sample工程) 44 | ```java 45 | /* 46 | devbase功能可以兼容DataSourceAutoConfiguration的功能,进行相应的配置即可 47 | */ 48 | @EnableDevBase 49 | @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 50 | public class CheeseApplication { 51 | public static void main(String[] args) { 52 | SpringApplication.run(CheeseApplication.class,args); 53 | } 54 | 55 | /** 56 | * mysql数据库的配置及数据库加载方式 57 | * 目前仅实现mysql的实现方式,后续会陆续增加pg oracle 等数据库的元数据加载实现 58 | * 59 | * @return 60 | */ 61 | @Bean 62 | public MysqlDialectCollector mysqlDialectCollector() { 63 | return new MysqlDialectCollector(); 64 | } 65 | } 66 | ``` 67 | 3. `application.properties`中配置 68 | ```properties 69 | server.port=8081 70 | logging.level.com.cheese.db.spring=debug 71 | spring.main.allow-bean-definition-overriding=true 72 | 73 | # devbase 配置 74 | ## devbase-db开启开关,默认开启 75 | devbase-db.enabled=true 76 | ## devbase-db使用默认配置,默认为false 77 | devbase-db.use-default-config=true 78 | 79 | # 多数据源配置 80 | devbase-db.configuration.sys.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 81 | devbase-db.configuration.sys.insert-key-property=id 82 | devbase-db.configuration.bus.insert-key-property=id 83 | 84 | ## 配置数据源 85 | devbase-db.config-data-source=sys 86 | ## 加载数据库的元数据,为数据库下的所有表生成基础增删改的方法 87 | ## 元数据加载的key 88 | devbase-db.data-sources.sys.scheme-key=sys 89 | ## 元数据加载数据库的名称,与url中的数据库名一致 90 | devbase-db.data-sources.sys.scheme-name=xxx_sys 91 | devbase-db.data-sources.sys.datasource-type=com.alibaba.druid.pool.DruidDataSource 92 | devbase-db.data-sources.sys.url=jdbc:mysql://localhost:3306/xxx_sys?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 93 | devbase-db.data-sources.sys.driver-class-name=com.mysql.cj.jdbc.Driver 94 | devbase-db.data-sources.sys.username=root 95 | devbase-db.data-sources.sys.password=root 96 | 97 | ## 其他数据源 可以配置多个 98 | devbase-db.data-sources.bus.scheme-key=bus 99 | devbase-db.data-sources.bus.scheme-name=xxx_bus 100 | devbase-db.data-sources.bus.datasource-type=com.alibaba.druid.pool.DruidDataSource 101 | devbase-db.data-sources.bus.url=jdbc:mysql://localhost:3306/xxx_bus?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 102 | devbase-db.data-sources.bus.driver-class-name=com.mysql.cj.jdbc.Driver 103 | devbase-db.data-sources.bus.username=root 104 | devbase-db.data-sources.bus.password=root 105 | 106 | 107 | ``` 108 | 109 | 110 | #### 微服务(这里提供基于ribbon的微服务调用方式) 111 | 112 | - 参考分支cheese-db-cloud中cheese-db-sample工程 113 | - 与单体服务不同的部分: 114 | - 服务提供者依赖使用 115 | ```xml 116 | 117 | com.cheese.db 118 | cheese-db-server-core 119 | 1.0.0 120 | 121 | ``` 122 | - 服务提供者配置: 123 | ```properties 124 | # -------------------eureka-------------- 125 | spring.application.name=server 126 | eureka.instance.instance-id=${spring.application.name}:@project.version@-${spring.cloud.client.ip-address}:${server.port} 127 | eureka.client.service-url.defaultZone=http://localhost:8000/eureka/ 128 | eureka.instance.lease-renewal-interval-in-seconds=5 129 | eureka.instance.lease-expiration-duration-in-seconds=10 130 | eureka.client.healthcheck.enabled=false 131 | eureka.instance.prefer-ip-address=true 132 | eureka.client.registry-fetch-interval-seconds=5 133 | ribbon.ServerListRefreshInterval=5000 134 | # -------------------cheese-db-server-------------- 135 | logging.level.com.cheese.db.server=debug 136 | spring.main.allow-bean-definition-overriding=true 137 | 138 | # devbase 配置 139 | ## devbase-db开启开关,默认开启 140 | devbase-db.server.enabled=true 141 | ## devbase-db使用默认配置,默认为false 142 | devbase-db.server.use-default-config=true 143 | ## 事务配置 144 | devbase-db.server.transaction-type=advisor 145 | ## 服务暴露方式 默认为feign 146 | devbase-db.server.exposer-type=default 147 | 148 | # 多数据源配置 149 | devbase-db.server.configuration.sys.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 150 | devbase-db.server.configuration.sys.insert-key-property=id 151 | devbase-db.server.configuration.bus.insert-key-property=id 152 | 153 | ## 配置数据源 154 | devbase-db.server.config-data-source=sys 155 | ## 加载数据库的元数据,为数据库下的所有表生成基础增删改的方法 156 | ## 元数据加载的key 157 | devbase-db.server.data-sources.sys.scheme-key=sys 158 | ## 元数据加载数据库的名称,与url中的数据库名一致 159 | devbase-db.server.data-sources.sys.scheme-name=db_sys 160 | devbase-db.server.data-sources.sys.datasource-type=com.alibaba.druid.pool.DruidDataSource 161 | devbase-db.server.data-sources.sys.url=jdbc:mysql://localhost:3306/db_sys?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 162 | devbase-db.server.data-sources.sys.driver-class-name=com.mysql.cj.jdbc.Driver 163 | devbase-db.server.data-sources.sys.username=root 164 | devbase-db.server.data-sources.sys.password=root 165 | 166 | ## 其他数据源 可以配置多个 167 | devbase-db.server.data-sources.bus.scheme-key=bus 168 | devbase-db.server.data-sources.bus.scheme-name=db_bus 169 | devbase-db.server.data-sources.bus.datasource-type=com.alibaba.druid.pool.DruidDataSource 170 | devbase-db.server.data-sources.bus.url=jdbc:mysql://localhost:3306/db_bus?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 171 | devbase-db.server.data-sources.bus.driver-class-name=com.mysql.cj.jdbc.Driver 172 | devbase-db.server.data-sources.bus.username=root 173 | devbase-db.server.data-sources.bus.password=root 174 | ``` 175 | - 服务消费者依赖使用 176 | ```xml 177 | 178 | com.cheese.db 179 | cheese-db-client-core 180 | 1.0.0 181 | 182 | ``` 183 | - 服务消费者配置: 184 | ```properties 185 | # -------------------eureka-------------- 186 | spring.application.name=client 187 | eureka.instance.instance-id=${spring.application.name}:@project.version@-${spring.cloud.client.ip-address}:${server.port} 188 | eureka.client.service-url.defaultZone=http://localhost:8000/eureka/ 189 | eureka.instance.lease-renewal-interval-in-seconds=5 190 | eureka.instance.lease-expiration-duration-in-seconds=10 191 | eureka.client.healthcheck.enabled=false 192 | eureka.instance.prefer-ip-address=true 193 | eureka.client.registry-fetch-interval-seconds=5 194 | ribbon.ServerListRefreshInterval=5000 195 | # -------------------cheese-db-client-------------- 196 | ## rpc调用的服务名称 197 | devbase-db.client.rpc-server=server 198 | ## rpc类型 199 | devbase-db.client.rpc-type=feign 200 | ``` -------------------------------------------------------------------------------- /cheese-db-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheese.db 8 | cheese-db-core 9 | 1.0.0 10 | 11 | 12 | 13 | 14 | org.slf4j 15 | slf4j-api 16 | 1.7.25 17 | compile 18 | 19 | 20 | org.mybatis 21 | mybatis 22 | 3.5.2 23 | compile 24 | 25 | 26 | com.github.pagehelper 27 | pagehelper 28 | 5.1.4 29 | compile 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-source-plugin 38 | 39 | true 40 | 41 | 42 | 43 | attach-sources 44 | compile 45 | 46 | jar 47 | 48 | 49 | 50 | 51 | 52 | org.apache.maven.plugins 53 | maven-deploy-plugin 54 | 2.8.1 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/DevBaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core; 2 | 3 | import com.cheese.db.core.props.MybatisConfig; 4 | import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; 5 | import org.apache.ibatis.executor.keygen.KeyGenerator; 6 | import org.apache.ibatis.session.Configuration; 7 | 8 | import java.util.Objects; 9 | 10 | /** 11 | * 继承自mybatis中Configuration类 12 | * 13 | * @author sobann 14 | */ 15 | public class DevBaseConfiguration extends Configuration { 16 | 17 | protected final DevBaseMapperRegistry mapperRegistry; 18 | protected Class keyGenerator; 19 | private String insertKeyProperty; 20 | 21 | private final String dbKey; 22 | 23 | public DevBaseConfiguration(String dbKey) { 24 | this.dbKey = dbKey; 25 | mapperRegistry = new DevBaseMapperRegistry(dbKey, this); 26 | } 27 | 28 | public boolean match(String dbKey) { 29 | return Objects.equals(this.dbKey, dbKey); 30 | } 31 | 32 | public boolean hasMapper(String dbKey, Class type) { 33 | return mapperRegistry.hasMapper(dbKey, type); 34 | } 35 | 36 | public void setMybatisConfig(MybatisConfig mybatisConfig) { 37 | this.setLogImpl(mybatisConfig.getLogImpl()); 38 | this.setMapUnderscoreToCamelCase(mybatisConfig.isMapUnderscoreToCamelCase()); 39 | this.setCacheEnabled(mybatisConfig.isCacheEnabled()); 40 | this.setUseGeneratedKeys(mybatisConfig.isUseGeneratedKeys()); 41 | this.keyGenerator = mybatisConfig.getKeyGenerator() == null ? Jdbc3KeyGenerator.class : mybatisConfig.getKeyGenerator(); 42 | this.insertKeyProperty = mybatisConfig.getInsertKeyProperty() == null ? "id" : mybatisConfig.getInsertKeyProperty(); 43 | } 44 | 45 | public Class getKeyGenerator() { 46 | return keyGenerator; 47 | } 48 | 49 | public void setKeyGenerator(Class keyGenerator) { 50 | this.keyGenerator = keyGenerator; 51 | } 52 | 53 | public String getInsertKeyProperty() { 54 | return insertKeyProperty; 55 | } 56 | 57 | public void setInsertKeyProperty(String insertKeyProperty) { 58 | this.insertKeyProperty = insertKeyProperty; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/DevBaseMapperRegistry.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core; 2 | 3 | import org.apache.ibatis.binding.MapperProxyFactory; 4 | import org.apache.ibatis.binding.MapperRegistry; 5 | import org.apache.ibatis.session.Configuration; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * 继承自mybatis中MapperRegistry类 12 | *

13 | * 暂未使用 14 | * 15 | * @author sobann 16 | */ 17 | public class DevBaseMapperRegistry extends MapperRegistry { 18 | 19 | private final Configuration config; 20 | private final String dbKey; 21 | private final Map, MapperProxyFactory> knownMappers = new HashMap<>(); 22 | 23 | public DevBaseMapperRegistry(String dbKey, Configuration config) { 24 | super(config); 25 | this.dbKey = dbKey; 26 | this.config = config; 27 | } 28 | 29 | public boolean hasMapper(String dbKey, Class type) { 30 | return knownMappers.containsKey(type); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/AbstractAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition; 2 | 3 | /** 4 | * 抽象类 5 | * 如果有公用的一些方法以及属性可以抽提到此类中 6 | *

7 | *

8 | * tip: 9 | * 10 | * @author sobann 11 | */ 12 | public abstract class AbstractAction implements Action { 13 | 14 | private final String dbKey; 15 | private final String code; 16 | 17 | public AbstractAction(String dbKey, String code) { 18 | this.dbKey = dbKey; 19 | this.code = code; 20 | } 21 | 22 | @Override 23 | public String getDbKey() { 24 | return dbKey; 25 | } 26 | 27 | @Override 28 | public String getCode() { 29 | return code; 30 | } 31 | 32 | public String getSqlSegment() { 33 | return null; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/AbstractTableAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition; 2 | 3 | /** 4 | * 关于直接对数据表操作的抽象action 5 | * 6 | * @author sobann 7 | */ 8 | public abstract class AbstractTableAction extends AbstractAction{ 9 | 10 | private final String tableName; 11 | 12 | public AbstractTableAction(String dbKey, String tableName) { 13 | super(dbKey, null); 14 | this.tableName = tableName; 15 | } 16 | 17 | public String getTableName() { 18 | return tableName; 19 | } 20 | 21 | @Override 22 | public String getCode() { 23 | // dbKey + tableName + ActionType 确认唯一Statement 24 | return this.getDbKey() + TOKEN_SEPARATOR + this.getTableName() + TOKEN_SEPARATOR + this.getActionType().name(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/Action.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition; 2 | 3 | 4 | import com.cheese.db.core.enums.ActionType; 5 | import com.cheese.db.core.support.DevBaseConstant; 6 | 7 | /** 8 | * 条件对象顶层接口 9 | * 10 | * @author sobann 11 | */ 12 | public interface Action extends DevBaseConstant { 13 | 14 | /** 15 | * 数据库标识 16 | * 17 | * @return 18 | */ 19 | String getDbKey(); 20 | 21 | /** 22 | * 可以理解为唯一名称空间 23 | * 24 | * @return 25 | */ 26 | String getCode(); 27 | 28 | /** 29 | * 操作类型 30 | * 31 | * @return 32 | */ 33 | ActionType getActionType(); 34 | } 35 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/Actions.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition; 2 | 3 | import com.cheese.db.core.condition.load.LoadAction; 4 | 5 | /** 6 | * 构建Action实例的工厂 7 | * 8 | * @author sobann 9 | */ 10 | public class Actions { 11 | 12 | public static LoadAction getLoad(String dbKey,String code){ 13 | return new LoadAction(dbKey, code); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/CommonSegmentProvider.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition; 2 | 3 | import com.cheese.db.core.condition.query.ComparatorKeyValue; 4 | import com.cheese.db.core.condition.query.LikeKeyValue; 5 | import com.cheese.db.core.condition.query.RangeKeyValue; 6 | import com.cheese.db.core.enums.Comparator; 7 | import com.cheese.db.core.enums.LikeType; 8 | import com.cheese.db.core.enums.RangeType; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | /** 16 | * 对于查询、修改、删除通用的sql片段的包装 17 | * 18 | * @author sobann 19 | */ 20 | public class CommonSegmentProvider { 21 | 22 | private static final String NO_SEGMENT = null; 23 | 24 | private final List rangeCdn; 25 | private final List likeCdn; 26 | private final List comparatorCdn; 27 | 28 | public CommonSegmentProvider() { 29 | this.rangeCdn = new ArrayList<>(8); 30 | this.likeCdn = new ArrayList<>(8); 31 | this.comparatorCdn = new ArrayList<>(8); 32 | } 33 | 34 | public void putLikeParam(String field, LikeType likeType, Object value) { 35 | likeCdn.add(new LikeKeyValue(field, value, likeType)); 36 | } 37 | 38 | public void putRangeParam(String field, RangeType rangeType, Object... rangeValues) { 39 | rangeCdn.add(new RangeKeyValue(field, rangeType, rangeValues)); 40 | } 41 | 42 | public void putComparatorParam(String field, Comparator comparator, Object value) { 43 | comparatorCdn.add(new ComparatorKeyValue(field, value, comparator)); 44 | } 45 | 46 | public String supportSqlSegment() { 47 | if (comparatorCdn.isEmpty() && likeCdn.isEmpty() && rangeCdn.isEmpty()) { 48 | return NO_SEGMENT; 49 | } 50 | StringBuilder segmentBuilder = new StringBuilder(); 51 | if (!rangeCdn.isEmpty()) { 52 | String inSegment = rangeCdn.stream().map(item -> String.format(" AND %s %s ", item.getKey(), String.format(item.getRangeType().getSegment(), Arrays.stream(item.getValues()).map(String::valueOf).sorted().collect(Collectors.joining(","))))).collect(Collectors.joining(" ")); 53 | segmentBuilder.append(inSegment); 54 | } 55 | if (!likeCdn.isEmpty()) { 56 | String likeSegment = likeCdn.stream().map(item -> String.format(" AND %s LIKE '%s'", item.getKey(), String.format(item.getLikeType().getSegment(), item.getValue()))).collect(Collectors.joining(" ")); 57 | segmentBuilder.append(likeSegment); 58 | } 59 | if (!comparatorCdn.isEmpty()) { 60 | String comparatorSegment = comparatorCdn.stream().map(item -> String.format(" AND %s %s '%s' ", item.getKey(), item.getRelation().getToken(), item.getValue())).collect(Collectors.joining(" ")); 61 | segmentBuilder.append(comparatorSegment); 62 | } 63 | return segmentBuilder.toString(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/load/LoadAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.load; 2 | 3 | import com.cheese.db.core.condition.AbstractAction; 4 | import com.cheese.db.core.enums.ActionType; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * load 11 | * 12 | * @author sobann 13 | */ 14 | public class LoadAction extends AbstractAction { 15 | 16 | private Long id; 17 | 18 | /** 19 | * 此属性为修改和新增准备 20 | */ 21 | private Map data; 22 | /** 23 | * 此属性作为所有sql的条件属性 24 | */ 25 | private Map param; 26 | 27 | public LoadAction(String dbKey, String code){ 28 | super(dbKey, code); 29 | this.data = new HashMap<>(8); 30 | this.param = new HashMap<>(8); 31 | } 32 | 33 | public void setData(Map data) { 34 | this.data = data; 35 | } 36 | 37 | public void setParam(Map param) { 38 | this.param = param; 39 | } 40 | 41 | public void putData(String field, Object val) { 42 | this.data.put(field, val); 43 | } 44 | 45 | public void putParam(String field, Object condition) { 46 | this.param.put(field, condition); 47 | } 48 | 49 | public Map getData() { 50 | return data; 51 | } 52 | 53 | public Map getParam() { 54 | return param; 55 | } 56 | 57 | public Long getId() { 58 | return id; 59 | } 60 | 61 | public void setId(Long id) { 62 | this.id = id; 63 | } 64 | 65 | @Override 66 | public ActionType getActionType() { 67 | return ActionType.LOAD; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/manager/DevBaseActionManager.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.manager; 2 | 3 | import com.cheese.db.core.condition.Action; 4 | 5 | /** 6 | * 默认的Action对象参数管理器 7 | * 通过对DevBaseActionManager的定义,可以完成: 8 | * 1.action的校验 9 | * 2.action增强 ===> 实现通用字段的注入等 10 | * 11 | * @author sobann 12 | */ 13 | public interface DevBaseActionManager { 14 | 15 | void manager(Action action); 16 | } 17 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/page/DevBasePage.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.page; 2 | 3 | import com.cheese.db.core.support.DevBaseConstant; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | /** 9 | * @author sobann 10 | */ 11 | public class DevBasePage implements IPage, DevBaseConstant { 12 | 13 | private List records = Collections.emptyList(); 14 | private long current; 15 | private long size; 16 | private long total; 17 | 18 | @Override 19 | public List getRecords() { 20 | return this.records; 21 | } 22 | 23 | @Override 24 | public void setRecords(List records) { 25 | this.records = records; 26 | } 27 | 28 | @Override 29 | public long getTotal() { 30 | return this.total; 31 | } 32 | 33 | @Override 34 | public void setTotal(long total) { 35 | this.total = total; 36 | } 37 | 38 | @Override 39 | public long getCurrent() { 40 | //current默认为0 41 | if (ZERO == this.current){ 42 | return DEFAULT_CURRENT; 43 | } 44 | return this.current; 45 | } 46 | 47 | @Override 48 | public void setCurrent(long current) { 49 | this.current = current; 50 | } 51 | 52 | @Override 53 | public long getSize() { 54 | //size默认为10 55 | if (ZERO == this.size){ 56 | return DEFAULT_SIZE; 57 | } 58 | return this.size; 59 | } 60 | 61 | @Override 62 | public void setSize(long size) { 63 | this.size = size; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/page/IPage.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.page; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | /** 7 | * @author sobann 8 | */ 9 | public interface IPage extends Serializable { 10 | 11 | List getRecords(); 12 | 13 | void setRecords(List records); 14 | 15 | long getTotal(); 16 | 17 | void setTotal(long total); 18 | 19 | long getSize(); 20 | 21 | void setSize(long size); 22 | 23 | long getCurrent(); 24 | 25 | void setCurrent(long current); 26 | } 27 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/page/PageFactory.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.page; 2 | 3 | /** 4 | * 分页构建工厂 5 | * 6 | * @author sobann 7 | */ 8 | public class PageFactory { 9 | 10 | /** 11 | * 创建基本的分页对象 12 | * 13 | * @param current 14 | * @param size 15 | * @param 16 | * @return 17 | */ 18 | public static IPage getPage(long current, long size) { 19 | DevBasePage devBasePage = new DevBasePage<>(); 20 | devBasePage.setCurrent(current); 21 | devBasePage.setSize(size); 22 | return devBasePage; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/query/ComparatorKeyValue.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.query; 2 | 3 | import com.cheese.db.core.enums.Comparator; 4 | 5 | /** 6 | * 键值关系comparator 7 | * 8 | * @author sobann 9 | */ 10 | public final class ComparatorKeyValue { 11 | 12 | private String key; 13 | 14 | private Object value; 15 | 16 | private Comparator relation; 17 | 18 | public ComparatorKeyValue(String key, Object value, Comparator relation) { 19 | this.key = key; 20 | this.value = value; 21 | this.relation = relation; 22 | } 23 | 24 | public String getKey() { 25 | return key; 26 | } 27 | 28 | public void setKey(String key) { 29 | this.key = key; 30 | } 31 | 32 | public Object getValue() { 33 | return value; 34 | } 35 | 36 | public void setValue(Object value) { 37 | this.value = value; 38 | } 39 | 40 | public Comparator getRelation() { 41 | return relation; 42 | } 43 | 44 | public void setRelation(Comparator relation) { 45 | this.relation = relation; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/query/LikeKeyValue.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.query; 2 | 3 | import com.cheese.db.core.enums.LikeType; 4 | 5 | /** 6 | * 键值关系like 7 | * 8 | * @author sobann 9 | */ 10 | public final class LikeKeyValue { 11 | 12 | private String key; 13 | 14 | private Object value; 15 | 16 | private LikeType likeType; 17 | 18 | public LikeKeyValue(String key, Object value, LikeType likeType) { 19 | this.key = key; 20 | this.value = value; 21 | this.likeType = likeType; 22 | } 23 | 24 | public String getKey() { 25 | return key; 26 | } 27 | 28 | public void setKey(String key) { 29 | this.key = key; 30 | } 31 | 32 | public Object getValue() { 33 | return value; 34 | } 35 | 36 | public void setValue(Object value) { 37 | this.value = value; 38 | } 39 | 40 | public LikeType getLikeType() { 41 | return likeType; 42 | } 43 | 44 | public void setLikeType(LikeType likeType) { 45 | this.likeType = likeType; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/query/RangeKeyValue.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.query; 2 | 3 | import com.cheese.db.core.enums.RangeType; 4 | 5 | /** 6 | * 范围关系range 7 | * 8 | * @author sobann 9 | */ 10 | public class RangeKeyValue { 11 | 12 | private String key; 13 | 14 | private Object[] values; 15 | 16 | private RangeType rangeType; 17 | 18 | 19 | public RangeKeyValue(String key, RangeType rangeType, Object... values) { 20 | this.key = key; 21 | this.values = values; 22 | this.rangeType = rangeType; 23 | } 24 | 25 | public String getKey() { 26 | return key; 27 | } 28 | 29 | public void setKey(String key) { 30 | this.key = key; 31 | } 32 | 33 | public Object[] getValues() { 34 | return values; 35 | } 36 | 37 | public void setValues(Object[] values) { 38 | this.values = values; 39 | } 40 | 41 | public RangeType getRangeType() { 42 | return rangeType; 43 | } 44 | 45 | public void setRangeType(RangeType rangeType) { 46 | this.rangeType = rangeType; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/simple/delete/DeleteTableAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.simple.delete; 2 | 3 | import com.cheese.db.core.condition.AbstractTableAction; 4 | import com.cheese.db.core.condition.CommonSegmentProvider; 5 | import com.cheese.db.core.enums.ActionType; 6 | import com.cheese.db.core.enums.Comparator; 7 | import com.cheese.db.core.enums.LikeType; 8 | import com.cheese.db.core.enums.RangeType; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * 删除操作 15 | * 16 | * @author sobann 17 | */ 18 | public class DeleteTableAction extends AbstractTableAction { 19 | 20 | private Map param; 21 | private final CommonSegmentProvider commonSegmentProvider; 22 | 23 | public DeleteTableAction(String dbKey, String tableName) { 24 | super(dbKey, tableName); 25 | this.param = new HashMap<>(8); 26 | this.commonSegmentProvider = new CommonSegmentProvider(); 27 | } 28 | 29 | public void putParam(String field, Object value) { 30 | this.param.put(field, value); 31 | } 32 | 33 | public Map getParam() { 34 | return param; 35 | } 36 | 37 | public void setParam(Map cdn) { 38 | this.param = cdn; 39 | } 40 | 41 | public void putLikeParam(String field, LikeType likeType, Object value) { 42 | commonSegmentProvider.putLikeParam(field, likeType, value); 43 | } 44 | 45 | public void putRangeParam(String field, RangeType rangeType, Object... rangeValues) { 46 | commonSegmentProvider.putRangeParam(field, rangeType, rangeValues); 47 | } 48 | 49 | public void putComparatorParam(String field, Comparator comparator, Object value) { 50 | commonSegmentProvider.putComparatorParam(field, comparator, value); 51 | } 52 | 53 | @Override 54 | public String getSqlSegment() { 55 | return commonSegmentProvider.supportSqlSegment(); 56 | } 57 | 58 | @Override 59 | public ActionType getActionType() { 60 | return ActionType.DELETE; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/simple/insert/InsertTableAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.simple.insert; 2 | 3 | import com.cheese.db.core.condition.AbstractTableAction; 4 | import com.cheese.db.core.enums.ActionType; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * 主键自增 使用Jdbc3KeyGenerator存在的问题 11 | * 1.数据表主键字段必须使用自增策略 12 | * 2.需要使用明确的TypeHandler来映射主键和数据库字段的关系,比如当前类中插入主键使用字段primary,java类型为Long,使用的字段处理器为LongTypeHandler (尝试使用Serializer 需要自定义一个 TypeHandler 否则会让主键无法回填哦) 13 | * 14 | * @author sobann 15 | */ 16 | public class InsertTableAction extends AbstractTableAction { 17 | 18 | private Map data; 19 | private Long id; 20 | 21 | public InsertTableAction(String dbKey, String tableName) { 22 | super(dbKey, tableName); 23 | this.data = new HashMap<>(8); 24 | } 25 | 26 | 27 | public Map getData() { 28 | return this.data; 29 | } 30 | 31 | public void putData(String field, Object value) { 32 | this.data.put(field, value); 33 | } 34 | 35 | public void setData(Map data) { 36 | this.data = data; 37 | } 38 | 39 | public Long getId() { 40 | return id; 41 | } 42 | 43 | public void setId(Long id) { 44 | this.id = id; 45 | } 46 | 47 | @Override 48 | public ActionType getActionType() { 49 | return ActionType.INSERT; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/simple/query/AbstractQueryAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.simple.query; 2 | 3 | import com.cheese.db.core.condition.AbstractTableAction; 4 | import com.cheese.db.core.enums.ActionType; 5 | import com.cheese.db.core.support.DevBaseConstant; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | /** 12 | * 查询功能 13 | * 14 | * @author sobann 15 | */ 16 | public abstract class AbstractQueryAction extends AbstractTableAction implements DevBaseConstant { 17 | 18 | private String sqlSelect = SQL_ALL; 19 | private Map param; 20 | /** 21 | * 条件传入实体实体,实体的参数最终都需要转入param中 22 | * 现阶段select语句script中仅使用#{ew.param.*}作为条件 23 | */ 24 | private T entity; 25 | 26 | public AbstractQueryAction(String dbKey, String tableName) { 27 | super(dbKey, tableName); 28 | this.param = new HashMap<>(8); 29 | } 30 | 31 | public void setSqlSelect(String sqlSelect) { 32 | this.sqlSelect = Objects.nonNull(sqlSelect) && !BLANK_STR.equals(sqlSelect) ? sqlSelect : SQL_ALL; 33 | } 34 | 35 | public String getSqlSelect() { 36 | return sqlSelect; 37 | } 38 | 39 | public void putParam(String field, Object value) { 40 | this.param.put(field, value); 41 | } 42 | 43 | public void setParam(Map param) { 44 | this.param = param; 45 | } 46 | 47 | protected Map getParam() { 48 | return this.param; 49 | } 50 | 51 | public T getEntity() { 52 | return entity; 53 | } 54 | 55 | public void setEntity(T entity) { 56 | 57 | this.entity = entity; 58 | } 59 | 60 | @Override 61 | public ActionType getActionType() { 62 | return ActionType.SELECT; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/simple/query/QueryTableAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.simple.query; 2 | 3 | import com.cheese.db.core.condition.CommonSegmentProvider; 4 | import com.cheese.db.core.enums.ActionType; 5 | import com.cheese.db.core.enums.Comparator; 6 | import com.cheese.db.core.enums.LikeType; 7 | import com.cheese.db.core.enums.RangeType; 8 | 9 | import java.util.Map; 10 | 11 | /** 12 | * 查询操作 使用mybatis的MapWrapper处理参数和返回 13 | * 14 | * @author sobann 15 | */ 16 | public class QueryTableAction extends AbstractQueryAction> { 17 | 18 | private final CommonSegmentProvider commonSegmentProvider; 19 | 20 | public QueryTableAction(String dbKey, String tableName) { 21 | super(dbKey, tableName); 22 | this.commonSegmentProvider = new CommonSegmentProvider(); 23 | } 24 | 25 | public void putLikeParam(String field, LikeType likeType, Object value) { 26 | commonSegmentProvider.putLikeParam(field, likeType, value); 27 | } 28 | 29 | public void putRangeParam(String field, RangeType rangeType, Object... rangeValues) { 30 | commonSegmentProvider.putRangeParam(field, rangeType, rangeValues); 31 | } 32 | 33 | public void putComparatorParam(String field, Comparator comparator, Object value) { 34 | commonSegmentProvider.putComparatorParam(field, comparator, value); 35 | } 36 | 37 | @Override 38 | public String getSqlSegment() { 39 | return commonSegmentProvider.supportSqlSegment(); 40 | } 41 | 42 | @Override 43 | public ActionType getActionType() { 44 | return ActionType.SELECT; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/condition/simple/update/UpdateTableAction.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.condition.simple.update; 2 | 3 | import com.cheese.db.core.condition.AbstractTableAction; 4 | import com.cheese.db.core.condition.CommonSegmentProvider; 5 | import com.cheese.db.core.enums.ActionType; 6 | import com.cheese.db.core.enums.Comparator; 7 | import com.cheese.db.core.enums.LikeType; 8 | import com.cheese.db.core.enums.RangeType; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * 修改操作 15 | * 16 | * @author sobann 17 | */ 18 | public class UpdateTableAction extends AbstractTableAction { 19 | 20 | private Map param; 21 | private Map data; 22 | private final CommonSegmentProvider commonSegmentProvider; 23 | 24 | public UpdateTableAction(String dbKey, String tableName) { 25 | super(dbKey, tableName); 26 | this.param = new HashMap<>(8); 27 | this.data = new HashMap<>(8); 28 | this.commonSegmentProvider = new CommonSegmentProvider(); 29 | } 30 | 31 | public void putParam(String field, Object value) { 32 | this.param.put(field, value); 33 | } 34 | 35 | public Map getParam() { 36 | return param; 37 | } 38 | 39 | public void setParam(Map cdn) { 40 | this.param = cdn; 41 | } 42 | 43 | public void putLikeParam(String field, LikeType likeType, Object value) { 44 | commonSegmentProvider.putLikeParam(field, likeType, value); 45 | } 46 | 47 | public void putRangeParam(String field, RangeType rangeType, Object... rangeValues) { 48 | commonSegmentProvider.putRangeParam(field, rangeType, rangeValues); 49 | } 50 | 51 | public void putComparatorParam(String field, Comparator comparator, Object value) { 52 | commonSegmentProvider.putComparatorParam(field, comparator, value); 53 | } 54 | 55 | public void putData(String field, Object value) { 56 | this.data.put(field, value); 57 | } 58 | 59 | public Map getData() { 60 | return data; 61 | } 62 | 63 | public void setData(Map data) { 64 | this.data = data; 65 | } 66 | 67 | @Override 68 | public String getSqlSegment() { 69 | return commonSegmentProvider.supportSqlSegment(); 70 | } 71 | 72 | @Override 73 | public ActionType getActionType() { 74 | return ActionType.UPDATE; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/enums/ActionType.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.enums; 2 | 3 | /** 4 | * action类型 5 | * 参考devbase早期版本的功能 6 | * 7 | * @author sobann 8 | */ 9 | public enum ActionType { 10 | INSERT, 11 | DELETE, 12 | UPDATE, 13 | SELECT, 14 | INSERT_OR_UPDATE, 15 | LOAD, 16 | BATCH 17 | } -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/enums/Comparator.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.enums; 2 | 3 | /** 4 | * 比较枚举 5 | * 6 | * @author sobann 7 | */ 8 | public enum Comparator { 9 | /** 10 | * 大于 11 | */ 12 | GT(">"), 13 | /** 14 | * 小于 15 | */ 16 | LT("<"), 17 | /** 18 | * 大于等于 19 | */ 20 | GTE(">="), 21 | /** 22 | * 小于等于 23 | */ 24 | LTE("<="), 25 | /** 26 | * 相等 27 | */ 28 | EQUALS("="), 29 | /** 30 | * 不相等 31 | */ 32 | NOT_EQUALS("!="); 33 | 34 | 35 | 36 | private final String token; 37 | 38 | Comparator(String token) { 39 | this.token = token; 40 | } 41 | 42 | public String getToken() { 43 | return token; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/enums/LikeType.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.enums; 2 | 3 | /** 4 | * 模糊匹配 5 | * 6 | * @author sobann 7 | */ 8 | public enum LikeType { 9 | 10 | /** 11 | * 左模糊 12 | */ 13 | LEFT("%%%s"), 14 | /** 15 | * 右模糊 16 | */ 17 | RIGHT("%s%%"), 18 | /** 19 | * 全模糊 20 | */ 21 | ALL("%%%s%%"); 22 | 23 | private final String segment; 24 | 25 | LikeType(String segment) { 26 | this.segment = segment; 27 | } 28 | 29 | public String getSegment() { 30 | return segment; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/enums/RangeType.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.enums; 2 | 3 | /** 4 | * 范围枚举 5 | * 6 | * @author sobann 7 | */ 8 | public enum RangeType { 9 | 10 | /** 11 | * 大于 12 | */ 13 | IN("IN (%s)"), 14 | /** 15 | * 小于 16 | */ 17 | NOT_IN("NOT IN (%s)"); 18 | 19 | 20 | private final String segment; 21 | 22 | RangeType(String segment) { 23 | this.segment = segment; 24 | } 25 | 26 | public String getSegment() { 27 | return segment; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/exception/DevBaseException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.exception; 2 | 3 | /** 4 | * devbase异常基类 5 | * 6 | * @author sobann 7 | */ 8 | public abstract class DevBaseException extends RuntimeException { 9 | 10 | public DevBaseException(String message) { 11 | super(message); 12 | } 13 | } -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/exception/ParamNotFountException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.exception; 2 | 3 | /** 4 | * action参数未找到异常 5 | * 6 | * @author sobann 7 | */ 8 | public class ParamNotFountException extends DevBaseException { 9 | public ParamNotFountException() { 10 | super("Devbase action param not found, pls check the parameters of the method definition"); 11 | } 12 | } -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/exception/ResultWrapperException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.exception; 2 | 3 | /** 4 | * 结果包装异常 5 | * 6 | * @author sobann 7 | */ 8 | public class ResultWrapperException extends DevBaseException { 9 | public ResultWrapperException(String message) { 10 | super("wrapper result error, the reason is " + message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/exception/StatementNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.exception; 2 | 3 | /** 4 | * MappedStatement 无法获取时抛出 5 | * 6 | * @author sobann 7 | */ 8 | public class StatementNotFoundException extends DevBaseException { 9 | 10 | public StatementNotFoundException(String statementId) { 11 | super("No MappedStatement witch id is " +statementId + " has been found"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/exception/UnknownActionTypeException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.exception; 2 | 3 | /** 4 | * 未知的ActionType异常 5 | * 6 | * @author sobann 7 | */ 8 | public class UnknownActionTypeException extends DevBaseException { 9 | public UnknownActionTypeException() { 10 | super("Non-existent actionType, pls check the action type of Action"); 11 | } 12 | } -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/mapper/DB.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.mapper; 2 | 3 | import com.cheese.db.core.condition.Action; 4 | import com.cheese.db.core.condition.page.IPage; 5 | import com.cheese.db.core.support.DevBaseConstant; 6 | import com.cheese.db.core.wrapper.WrapperResult; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * 默认持久层注册实例 14 | * 15 | * @author sobann 16 | */ 17 | public interface DB { 18 | /** 19 | * 执行action获取结果,此方法为通用方法, 20 | * String 为 21 | * 默认result是map时 22 | * 23 | * @param action 24 | * @return 25 | */ 26 | WrapperResult, R> doAction(@Param(DevBaseConstant.ACTION_EW) Action action); 27 | 28 | /** 29 | * 执行action获取结果 30 | * 使用实例进行包装 31 | * 32 | * @param action 33 | * @param wrapperClazz 34 | * @return 35 | */ 36 | WrapperResult doAction(@Param(DevBaseConstant.ACTION_EW) Action action, Class wrapperClazz); 37 | 38 | /** 39 | * 查询元素列表 40 | * 41 | * @param action 42 | * @return 43 | */ 44 | List> doActionGetList(@Param(DevBaseConstant.ACTION_EW) Action action); 45 | 46 | /** 47 | * 查询元素列表 48 | * 49 | * @param action 50 | * @param clazz 51 | * @param 52 | * @return 53 | */ 54 | List doActionGetList(@Param(DevBaseConstant.ACTION_EW) Action action, Class clazz); 55 | 56 | /** 57 | * 查询单个元素 58 | * 59 | * @param action 60 | * @return 61 | */ 62 | Map doActionGetOne(@Param(DevBaseConstant.ACTION_EW) Action action); 63 | 64 | /** 65 | * 查询单个元素 66 | * 67 | * @param action 68 | * @param clazz 69 | * @param 70 | * @return 71 | */ 72 | T doActionGetOne(@Param(DevBaseConstant.ACTION_EW) Action action, Class clazz); 73 | 74 | /** 75 | * 查询元素分页 76 | * 77 | * @param action 78 | * @param page 79 | * @return 80 | */ 81 | IPage> doActionGetPage(IPage> page, @Param(DevBaseConstant.ACTION_EW) Action action); 82 | 83 | /** 84 | * 查询元素分页 85 | * 86 | * @param action 87 | * @param page 88 | * @param clazz 89 | * @param 90 | * @return 91 | */ 92 | IPage doActionGetPage(IPage page, @Param(DevBaseConstant.ACTION_EW) Action action, Class clazz); 93 | } 94 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/props/DataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.props; 2 | 3 | import javax.sql.DataSource; 4 | 5 | /** 6 | * 数据源配置 7 | * 8 | * @author sobann 9 | */ 10 | public class DataSourceConfig { 11 | 12 | private Class datasourceType; 13 | private String url; 14 | private String driverClassName; 15 | private String username; 16 | private String password; 17 | private String schemeName; 18 | private String schemeKey; 19 | private boolean autoLoad = true; 20 | 21 | private int initialSize = 0; 22 | private int maxActive = 8; 23 | private int minIdle = 0; 24 | private int maxIdle = 8; 25 | private long maxWait = -1; 26 | 27 | public String getUrl() { 28 | return url; 29 | } 30 | 31 | public void setUrl(String url) { 32 | this.url = url; 33 | } 34 | 35 | public String getDriverClassName() { 36 | return driverClassName; 37 | } 38 | 39 | public void setDriverClassName(String driverClassName) { 40 | this.driverClassName = driverClassName; 41 | } 42 | 43 | public String getUsername() { 44 | return username; 45 | } 46 | 47 | public void setUsername(String username) { 48 | this.username = username; 49 | } 50 | 51 | public String getPassword() { 52 | return password; 53 | } 54 | 55 | public void setPassword(String password) { 56 | this.password = password; 57 | } 58 | 59 | public int getInitialSize() { 60 | return initialSize; 61 | } 62 | 63 | public void setInitialSize(int initialSize) { 64 | this.initialSize = initialSize; 65 | } 66 | 67 | public int getMaxActive() { 68 | return maxActive; 69 | } 70 | 71 | public void setMaxActive(int maxActive) { 72 | this.maxActive = maxActive; 73 | } 74 | 75 | public int getMinIdle() { 76 | return minIdle; 77 | } 78 | 79 | public void setMinIdle(int minIdle) { 80 | this.minIdle = minIdle; 81 | } 82 | 83 | public int getMaxIdle() { 84 | return maxIdle; 85 | } 86 | 87 | public void setMaxIdle(int maxIdle) { 88 | this.maxIdle = maxIdle; 89 | } 90 | 91 | public long getMaxWait() { 92 | return maxWait; 93 | } 94 | 95 | public void setMaxWait(long maxWait) { 96 | this.maxWait = maxWait; 97 | } 98 | 99 | public Class getDatasourceType() { 100 | return datasourceType; 101 | } 102 | 103 | public void setDatasourceType(Class datasourceType) { 104 | this.datasourceType = datasourceType; 105 | } 106 | 107 | public boolean isAutoLoad() { 108 | return autoLoad; 109 | } 110 | 111 | public void setAutoLoad(boolean autoLoad) { 112 | this.autoLoad = autoLoad; 113 | } 114 | 115 | public String getSchemeName() { 116 | return schemeName; 117 | } 118 | 119 | public void setSchemeName(String schemeName) { 120 | this.schemeName = schemeName; 121 | } 122 | 123 | public String getSchemeKey() { 124 | return schemeKey; 125 | } 126 | 127 | public void setSchemeKey(String schemeKey) { 128 | this.schemeKey = schemeKey; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/props/MybatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.props; 2 | 3 | import org.apache.ibatis.executor.keygen.KeyGenerator; 4 | import org.apache.ibatis.io.VFS; 5 | import org.apache.ibatis.logging.Log; 6 | import org.apache.ibatis.session.AutoMappingBehavior; 7 | import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior; 8 | import org.apache.ibatis.session.ExecutorType; 9 | import org.apache.ibatis.session.LocalCacheScope; 10 | import org.apache.ibatis.type.JdbcType; 11 | 12 | /** 13 | * mybatis配置项 14 | * 15 | * @author sobann 16 | */ 17 | public class MybatisConfig { 18 | 19 | private boolean safeRowBoundsEnabled; 20 | private boolean safeResultHandlerEnabled = true; 21 | private boolean mapUnderscoreToCamelCase; 22 | private boolean aggressiveLazyLoading; 23 | private boolean multipleResultSetsEnabled = true; 24 | private boolean useGeneratedKeys; 25 | private Class KeyGenerator; 26 | private String insertKeyProperty; 27 | private boolean useColumnLabel = true; 28 | private boolean cacheEnabled = true; 29 | private boolean callSettersOnNulls; 30 | private boolean useActualParamName = true; 31 | private boolean returnInstanceForEmptyRow; 32 | private String logPrefix; 33 | private Class logImpl; 34 | private Class vfsImpl; 35 | private LocalCacheScope localCacheScope = LocalCacheScope.SESSION; 36 | private JdbcType jdbcTypeForNull = JdbcType.OTHER; 37 | private Integer defaultStatementTimeout; 38 | private Integer defaultFetchSize; 39 | private ExecutorType defaultExecutorType = ExecutorType.SIMPLE; 40 | private AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL; 41 | private AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE; 42 | private boolean lazyLoadingEnabled = false; 43 | private String databaseId; 44 | private Class configurationFactory; 45 | 46 | public boolean isSafeRowBoundsEnabled() { 47 | return safeRowBoundsEnabled; 48 | } 49 | 50 | public void setSafeRowBoundsEnabled(boolean safeRowBoundsEnabled) { 51 | this.safeRowBoundsEnabled = safeRowBoundsEnabled; 52 | } 53 | 54 | public boolean isSafeResultHandlerEnabled() { 55 | return safeResultHandlerEnabled; 56 | } 57 | 58 | public void setSafeResultHandlerEnabled(boolean safeResultHandlerEnabled) { 59 | this.safeResultHandlerEnabled = safeResultHandlerEnabled; 60 | } 61 | 62 | public boolean isMapUnderscoreToCamelCase() { 63 | return mapUnderscoreToCamelCase; 64 | } 65 | 66 | public void setMapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) { 67 | this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase; 68 | } 69 | 70 | public boolean isAggressiveLazyLoading() { 71 | return aggressiveLazyLoading; 72 | } 73 | 74 | public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) { 75 | this.aggressiveLazyLoading = aggressiveLazyLoading; 76 | } 77 | 78 | public boolean isMultipleResultSetsEnabled() { 79 | return multipleResultSetsEnabled; 80 | } 81 | 82 | public void setMultipleResultSetsEnabled(boolean multipleResultSetsEnabled) { 83 | this.multipleResultSetsEnabled = multipleResultSetsEnabled; 84 | } 85 | 86 | public boolean isUseGeneratedKeys() { 87 | return useGeneratedKeys; 88 | } 89 | 90 | public void setUseGeneratedKeys(boolean useGeneratedKeys) { 91 | this.useGeneratedKeys = useGeneratedKeys; 92 | } 93 | 94 | public boolean isUseColumnLabel() { 95 | return useColumnLabel; 96 | } 97 | 98 | public void setUseColumnLabel(boolean useColumnLabel) { 99 | this.useColumnLabel = useColumnLabel; 100 | } 101 | 102 | public boolean isCacheEnabled() { 103 | return cacheEnabled; 104 | } 105 | 106 | public void setCacheEnabled(boolean cacheEnabled) { 107 | this.cacheEnabled = cacheEnabled; 108 | } 109 | 110 | public boolean isCallSettersOnNulls() { 111 | return callSettersOnNulls; 112 | } 113 | 114 | public void setCallSettersOnNulls(boolean callSettersOnNulls) { 115 | this.callSettersOnNulls = callSettersOnNulls; 116 | } 117 | 118 | public boolean isUseActualParamName() { 119 | return useActualParamName; 120 | } 121 | 122 | public void setUseActualParamName(boolean useActualParamName) { 123 | this.useActualParamName = useActualParamName; 124 | } 125 | 126 | public boolean isReturnInstanceForEmptyRow() { 127 | return returnInstanceForEmptyRow; 128 | } 129 | 130 | public void setReturnInstanceForEmptyRow(boolean returnInstanceForEmptyRow) { 131 | this.returnInstanceForEmptyRow = returnInstanceForEmptyRow; 132 | } 133 | 134 | public String getLogPrefix() { 135 | return logPrefix; 136 | } 137 | 138 | public void setLogPrefix(String logPrefix) { 139 | this.logPrefix = logPrefix; 140 | } 141 | 142 | public Class getLogImpl() { 143 | return logImpl; 144 | } 145 | 146 | public void setLogImpl(Class logImpl) { 147 | this.logImpl = logImpl; 148 | } 149 | 150 | public Class getVfsImpl() { 151 | return vfsImpl; 152 | } 153 | 154 | public void setVfsImpl(Class vfsImpl) { 155 | this.vfsImpl = vfsImpl; 156 | } 157 | 158 | public LocalCacheScope getLocalCacheScope() { 159 | return localCacheScope; 160 | } 161 | 162 | public void setLocalCacheScope(LocalCacheScope localCacheScope) { 163 | this.localCacheScope = localCacheScope; 164 | } 165 | 166 | public JdbcType getJdbcTypeForNull() { 167 | return jdbcTypeForNull; 168 | } 169 | 170 | public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) { 171 | this.jdbcTypeForNull = jdbcTypeForNull; 172 | } 173 | 174 | public Integer getDefaultStatementTimeout() { 175 | return defaultStatementTimeout; 176 | } 177 | 178 | public void setDefaultStatementTimeout(Integer defaultStatementTimeout) { 179 | this.defaultStatementTimeout = defaultStatementTimeout; 180 | } 181 | 182 | public Integer getDefaultFetchSize() { 183 | return defaultFetchSize; 184 | } 185 | 186 | public void setDefaultFetchSize(Integer defaultFetchSize) { 187 | this.defaultFetchSize = defaultFetchSize; 188 | } 189 | 190 | public ExecutorType getDefaultExecutorType() { 191 | return defaultExecutorType; 192 | } 193 | 194 | public void setDefaultExecutorType(ExecutorType defaultExecutorType) { 195 | this.defaultExecutorType = defaultExecutorType; 196 | } 197 | 198 | public AutoMappingBehavior getAutoMappingBehavior() { 199 | return autoMappingBehavior; 200 | } 201 | 202 | public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) { 203 | this.autoMappingBehavior = autoMappingBehavior; 204 | } 205 | 206 | public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() { 207 | return autoMappingUnknownColumnBehavior; 208 | } 209 | 210 | public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) { 211 | this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior; 212 | } 213 | 214 | public boolean isLazyLoadingEnabled() { 215 | return lazyLoadingEnabled; 216 | } 217 | 218 | public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) { 219 | this.lazyLoadingEnabled = lazyLoadingEnabled; 220 | } 221 | 222 | public String getDatabaseId() { 223 | return databaseId; 224 | } 225 | 226 | public void setDatabaseId(String databaseId) { 227 | this.databaseId = databaseId; 228 | } 229 | 230 | public Class getConfigurationFactory() { 231 | return configurationFactory; 232 | } 233 | 234 | public void setConfigurationFactory(Class configurationFactory) { 235 | this.configurationFactory = configurationFactory; 236 | } 237 | 238 | public Class getKeyGenerator() { 239 | return KeyGenerator; 240 | } 241 | 242 | public void setKeyGenerator(Class keyGenerator) { 243 | KeyGenerator = keyGenerator; 244 | } 245 | 246 | public String getInsertKeyProperty() { 247 | return insertKeyProperty; 248 | } 249 | 250 | public void setInsertKeyProperty(String insertKeyProperty) { 251 | this.insertKeyProperty = insertKeyProperty; 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/proxy/DevBaseDBMapperMethod.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.proxy; 2 | 3 | import com.cheese.db.core.condition.Action; 4 | import com.cheese.db.core.condition.page.IPage; 5 | import com.cheese.db.core.support.ConfigurationSupport; 6 | import com.cheese.db.core.support.DevBaseConstant; 7 | import com.cheese.db.core.wrapper.BeanWrapperResult; 8 | import com.cheese.db.core.wrapper.MapWrapperResult; 9 | import com.github.pagehelper.Page; 10 | import com.github.pagehelper.PageHelper; 11 | import org.apache.ibatis.binding.BindingException; 12 | import org.apache.ibatis.mapping.MappedStatement; 13 | import org.apache.ibatis.session.Configuration; 14 | import org.apache.ibatis.session.SqlSession; 15 | 16 | import java.lang.reflect.Method; 17 | import java.util.Arrays; 18 | import java.util.Objects; 19 | 20 | /** 21 | * devbase基于方法级别的代理 22 | * 23 | * @author sobann 24 | */ 25 | public class DevBaseDBMapperMethod implements DevBaseConstant { 26 | 27 | private final DevBaseDBSqlCommand command; 28 | private final DevBaseDBMethodSignature method; 29 | 30 | public DevBaseDBMapperMethod(DevBaseDBSqlCommand command, DevBaseDBMethodSignature method) { 31 | this.command = command; 32 | this.method = method; 33 | } 34 | 35 | /** 36 | * 根据sqlSession实例和参数 37 | * 38 | * @param sqlSession 39 | * @return 40 | */ 41 | public Object execute(SqlSession sqlSession, Object[] args) { 42 | Object result; 43 | switch (command.getType()) { 44 | //目前INSERT、UPDATE、DELETE、SELECT都可在doAction通用方法中进行操作,通用方法使用WrapperResult进行封装返回 45 | case INSERT: { 46 | Object param = method.convertArgsToSqlCommandParam(args); 47 | result = rowCountResult(sqlSession.insert(command.getName(), param)); 48 | break; 49 | } 50 | case UPDATE: { 51 | Object param = method.convertArgsToSqlCommandParam(args); 52 | result = rowCountResult(sqlSession.update(command.getName(), param)); 53 | break; 54 | } 55 | case DELETE: { 56 | Object param = method.convertArgsToSqlCommandParam(args); 57 | result = rowCountResult(sqlSession.delete(command.getName(), param)); 58 | break; 59 | } 60 | case SELECT: 61 | Object param = method.convertArgsToSqlCommandParam(args); 62 | if (method.returnsVoid() && method.hasResultHandler()) { 63 | result = null; 64 | } else if (method.returnsMany()) { 65 | result = sqlSession.selectList(command.getName(), param); 66 | } else { 67 | //修改了此处 分页查询 68 | if (IPage.class.isAssignableFrom(method.getReturnType()) && args != null 69 | && IPage.class.isAssignableFrom(args[0].getClass())) { 70 | IPage page = (IPage)args[0]; 71 | //fixme 此处分页写死了 必须使用PageHelper 72 | Page pageCondition = PageHelper.startPage((int)page.getCurrent(), (int)page.getSize()); 73 | page.setRecords(sqlSession.selectList(command.getName(), param)); 74 | page.setTotal(pageCondition.getTotal()); 75 | result = page; 76 | }else { 77 | //查询单个 78 | result = sqlSession.selectOne(command.getName(), param); 79 | } 80 | } 81 | break; 82 | case FLUSH: 83 | result = sqlSession.flushStatements(); 84 | break; 85 | default: 86 | throw new BindingException("Unknown execution method for: " + command.getName()); 87 | } 88 | if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { 89 | throw new BindingException("Mapper method '" + command.getName() 90 | + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); 91 | } 92 | //返回数据是否需要使用WrapperResult进行包装 93 | if (method.getNeedWrapperResult()) { 94 | /* 95 | 参数未传递wrapperClazz时,使用默认的MapWrapperResult包装参数 96 | tip: 传入自定义BeanWrapper时,对象中必须包含一个合适的result成员变量以及提供空参数构造方式以及相应的getSet方法 97 | */ 98 | Object wrapperClazz = Arrays.stream(args).filter(arg -> arg instanceof Class).findFirst().orElse(null); 99 | if (!Objects.isNull(wrapperClazz)) { 100 | //使用beanWrapper 101 | BeanWrapperResult beanWrapperResult = new BeanWrapperResult((Class) wrapperClazz); 102 | result = beanWrapperResult.wrapperResult(result); 103 | } else { 104 | MapWrapperResult wrapperResult = MapWrapperResult.Builder.build(); 105 | result = wrapperResult.wrapperResult(result); 106 | } 107 | } 108 | return result; 109 | } 110 | 111 | private Object rowCountResult(int rowCount) { 112 | final Object result; 113 | if (method.returnsVoid()) { 114 | result = null; 115 | } else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) { 116 | result = rowCount; 117 | } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) { 118 | result = (long) rowCount; 119 | } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) { 120 | result = rowCount > 0; 121 | } else { 122 | throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType()); 123 | } 124 | return result; 125 | } 126 | 127 | 128 | /** 129 | * DevBaseDBMapperMethod方法建造者 130 | * 131 | * @author sobann 132 | */ 133 | public static class Builder extends ConfigurationSupport { 134 | 135 | private final Class mapperInterface; 136 | private final Method method; 137 | private final Action action; 138 | private final Configuration config; 139 | 140 | public Builder(Class mapperInterface, Method method, Action action, Configuration config) { 141 | this.mapperInterface = mapperInterface; 142 | this.method = method; 143 | this.action = action; 144 | this.config = config; 145 | } 146 | 147 | public DevBaseDBMapperMethod build() { 148 | //判断当前method是否是 DevBaseConstant.DEFAULT_WRAPPER_RESULT_METHOD_NAMES包含的方法,如果是,则将DevBaseDBMethodSignature.needWrapperResult设置为true 149 | boolean needWrapperResult = resolveNeedWrapperResult(method); 150 | //注入的statement 151 | MappedStatement mappedStatement = resolveMappedStatement(mapperInterface, action.getCode(), method.getDeclaringClass(), config); 152 | DevBaseDBSqlCommand command = new DevBaseDBSqlCommand(mappedStatement.getId(), mappedStatement.getSqlCommandType()); 153 | //returnType从配置的resultMap中获取,默认为Map 154 | Class returnType = null; 155 | //非包装类方法当前的returnType根据mappedStatement类型判断 156 | if (!needWrapperResult){ 157 | returnType = resolveReturnType(method, mapperInterface); 158 | if (returnType == null) { 159 | //解析失败时,直接是用注册时元素的类型 160 | returnType = getResultMapClassType(mappedStatement); 161 | } 162 | }else { 163 | returnType = resolveReturnType(mappedStatement); 164 | } 165 | DevBaseDBMethodSignature signature = new DevBaseDBMethodSignature(config, mapperInterface, method, returnType, needWrapperResult); 166 | //被建造的代理方法 167 | return new DevBaseDBMapperMethod(command, signature); 168 | } 169 | 170 | 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/proxy/DevBaseDBMethodSignature.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.proxy; 2 | 3 | import org.apache.ibatis.annotations.MapKey; 4 | import org.apache.ibatis.binding.BindingException; 5 | import org.apache.ibatis.cursor.Cursor; 6 | import org.apache.ibatis.reflection.ParamNameResolver; 7 | import org.apache.ibatis.session.Configuration; 8 | import org.apache.ibatis.session.ResultHandler; 9 | import org.apache.ibatis.session.RowBounds; 10 | 11 | import java.lang.reflect.Method; 12 | import java.util.Map; 13 | 14 | /** 15 | * 持久层方法元数据封装 16 | * 17 | * @author sobann 18 | */ 19 | public class DevBaseDBMethodSignature { 20 | 21 | private final boolean returnsMany; 22 | private final boolean returnsMap; 23 | private final boolean returnsVoid; 24 | private final boolean returnsCursor; 25 | private final Class returnType; 26 | private final String mapKey; 27 | private final Integer resultHandlerIndex; 28 | private final Integer rowBoundsIndex; 29 | private final ParamNameResolver paramNameResolver; 30 | private final boolean needWrapperResult; 31 | 32 | public DevBaseDBMethodSignature(Configuration configuration, Class mapperInterface, Method method, Class type, boolean needWrapperResult) { 33 | this.needWrapperResult = needWrapperResult; 34 | this.returnType = type; 35 | this.returnsVoid = void.class.equals(this.returnType); 36 | this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray()); 37 | this.returnsCursor = Cursor.class.equals(this.returnType); 38 | this.mapKey = getMapKey(method); 39 | this.returnsMap = (this.mapKey != null); 40 | this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class); 41 | this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class); 42 | this.paramNameResolver = new ParamNameResolver(configuration, method); 43 | } 44 | 45 | public Object convertArgsToSqlCommandParam(Object[] args) { 46 | return paramNameResolver.getNamedParams(args); 47 | } 48 | 49 | public boolean hasRowBounds() { 50 | return rowBoundsIndex != null; 51 | } 52 | 53 | public RowBounds extractRowBounds(Object[] args) { 54 | return hasRowBounds() ? (RowBounds) args[rowBoundsIndex] : null; 55 | } 56 | 57 | public boolean hasResultHandler() { 58 | return resultHandlerIndex != null; 59 | } 60 | 61 | public ResultHandler extractResultHandler(Object[] args) { 62 | return hasResultHandler() ? (ResultHandler) args[resultHandlerIndex] : null; 63 | } 64 | 65 | public String getMapKey() { 66 | return mapKey; 67 | } 68 | 69 | public Class getReturnType() { 70 | return returnType; 71 | } 72 | 73 | public boolean returnsMany() { 74 | return returnsMany; 75 | } 76 | 77 | public boolean returnsMap() { 78 | return returnsMap; 79 | } 80 | 81 | public boolean returnsVoid() { 82 | return returnsVoid; 83 | } 84 | 85 | public boolean returnsCursor() { 86 | return returnsCursor; 87 | } 88 | 89 | public Boolean getNeedWrapperResult() { 90 | return needWrapperResult; 91 | } 92 | 93 | private Integer getUniqueParamIndex(Method method, Class paramType) { 94 | Integer index = null; 95 | final Class[] argTypes = method.getParameterTypes(); 96 | for (int i = 0; i < argTypes.length; i++) { 97 | if (paramType.isAssignableFrom(argTypes[i])) { 98 | if (index == null) { 99 | index = i; 100 | } else { 101 | throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters"); 102 | } 103 | } 104 | } 105 | return index; 106 | } 107 | 108 | private String getMapKey(Method method) { 109 | String mapKey = null; 110 | if (Map.class.isAssignableFrom(method.getReturnType())) { 111 | final MapKey mapKeyAnnotation = method.getAnnotation(MapKey.class); 112 | if (mapKeyAnnotation != null) { 113 | mapKey = mapKeyAnnotation.value(); 114 | } 115 | } 116 | return mapKey; 117 | } 118 | } -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/proxy/DevBaseDBSqlCommand.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.proxy; 2 | 3 | 4 | import org.apache.ibatis.mapping.SqlCommandType; 5 | 6 | /** 7 | * mybatis相关statement的msId以及sql类型 8 | * 9 | * @author sobann 10 | */ 11 | public class DevBaseDBSqlCommand { 12 | 13 | private final String name; 14 | private final SqlCommandType type; 15 | 16 | public DevBaseDBSqlCommand(String name, SqlCommandType type){ 17 | this.name = name; 18 | this.type = type; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | public SqlCommandType getType() { 26 | return type; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/proxy/DevBaseMapperProxy.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.proxy; 2 | 3 | import com.cheese.db.core.condition.Action; 4 | import com.cheese.db.core.condition.manager.DevBaseActionManager; 5 | import org.apache.ibatis.reflection.ExceptionUtil; 6 | import org.apache.ibatis.session.SqlSession; 7 | 8 | import java.io.Serializable; 9 | import java.lang.invoke.MethodHandles; 10 | import java.lang.reflect.Constructor; 11 | import java.lang.reflect.InvocationHandler; 12 | import java.lang.reflect.Method; 13 | import java.util.Arrays; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | /** 18 | * devbase持久层代理 19 | * 20 | * @author sobann 21 | */ 22 | public class DevBaseMapperProxy implements InvocationHandler, Serializable { 23 | 24 | private final Map sqlSessions; 25 | private final Class mapperInterface; 26 | private final Map> methodCache; 27 | private final DevBaseActionManager devBaseActionManager; 28 | 29 | public DevBaseMapperProxy(Map sqlSessions, Class mapperInterface, 30 | Map> methodCache, 31 | DevBaseActionManager devBaseActionManager) { 32 | this.sqlSessions = sqlSessions; 33 | this.mapperInterface = mapperInterface; 34 | this.methodCache = methodCache; 35 | this.devBaseActionManager = devBaseActionManager; 36 | } 37 | 38 | @Override 39 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 40 | try { 41 | if (Object.class.equals(method.getDeclaringClass())) { 42 | return method.invoke(this, args); 43 | } else if (method.isDefault()) { 44 | return invokeDefaultMethod(proxy, method, args); 45 | } 46 | } catch (Throwable t) { 47 | throw ExceptionUtil.unwrapThrowable(t); 48 | } 49 | 50 | //获取参数 51 | Action action = this.obtainActionFromParam(args); 52 | devBaseActionManager.manager(action); 53 | final DevBaseDBMapperMethod mapperMethod = cachedMapperMethod(method, action); 54 | SqlSession currentSqlSession = getCurrentSqlSession(action); 55 | return mapperMethod.execute(currentSqlSession, args); 56 | } 57 | 58 | private DevBaseDBMapperMethod cachedMapperMethod(Method method, Action action) { 59 | //上限根据数据库中配置的sql上限决定 60 | Map devbaseMapperMethodMap = this.methodCache.computeIfAbsent(method, k -> new HashMap<>(256)); 61 | //缓存 method -> code -> MapperMethod 62 | if (devbaseMapperMethodMap.containsKey(action.getCode())) return devbaseMapperMethodMap.get(action.getCode()); 63 | //根据方法和参数code构造对应的方法 通过msId在configuration中获取到对应的statement,封装参数、返回值、查询类型等内容 64 | DevBaseDBMapperMethod codeMethod = new DevBaseDBMapperMethod.Builder(mapperInterface, method, action, sqlSessions.get(action.getDbKey()).getConfiguration()).build(); 65 | devbaseMapperMethodMap.put(action.getCode(), codeMethod); 66 | return codeMethod; 67 | } 68 | 69 | private SqlSession getCurrentSqlSession(Action action) { 70 | String dbKey = action.getDbKey(); 71 | return sqlSessions.get(dbKey); 72 | } 73 | 74 | private Action obtainActionFromParam(Object[] args) { 75 | return (Action) Arrays.stream(args).filter(item -> Action.class.isAssignableFrom(item.getClass())).findAny().orElse(null); 76 | } 77 | 78 | 79 | private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) 80 | throws Throwable { 81 | final Constructor constructor = MethodHandles.Lookup.class 82 | .getDeclaredConstructor(Class.class, int.class); 83 | if (!constructor.isAccessible()) { 84 | constructor.setAccessible(true); 85 | } 86 | final Class declaringClass = method.getDeclaringClass(); 87 | return constructor.newInstance(declaringClass, 88 | MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED | 89 | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC) 90 | .unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/proxy/DevBaseMapperProxyFactory.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.proxy; 2 | 3 | import com.cheese.db.core.condition.manager.DevBaseActionManager; 4 | import org.apache.ibatis.session.SqlSession; 5 | 6 | import java.lang.reflect.Method; 7 | import java.lang.reflect.Proxy; 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * devbase持久层代理生成工厂 13 | * 14 | * @author sobann 15 | */ 16 | public class DevBaseMapperProxyFactory { 17 | 18 | private final Class mapperInterface; 19 | private final Map sqlSessions; 20 | private final DevBaseActionManager devBaseActionManager; 21 | private Map> methodCache = new ConcurrentHashMap<>(); 22 | 23 | public DevBaseMapperProxyFactory(Class mapperInterface, Map sqlSessions, DevBaseActionManager devBaseActionManager) { 24 | this.mapperInterface = mapperInterface; 25 | this.sqlSessions = sqlSessions; 26 | this.devBaseActionManager = devBaseActionManager == null ? action -> {} : devBaseActionManager; 27 | } 28 | 29 | @SuppressWarnings("unchecked") 30 | protected T newInstance(DevBaseMapperProxy mapperProxy) { 31 | return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[]{mapperInterface}, mapperProxy); 32 | } 33 | 34 | public T newInstance() { 35 | final DevBaseMapperProxy mapperProxy = new DevBaseMapperProxy<>(sqlSessions, mapperInterface, methodCache, devBaseActionManager); 36 | return newInstance(mapperProxy); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/support/ConfigurationSupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.support; 2 | 3 | import com.cheese.db.core.exception.StatementNotFoundException; 4 | import org.apache.ibatis.mapping.MappedStatement; 5 | import org.apache.ibatis.mapping.ResultMap; 6 | import org.apache.ibatis.mapping.SqlCommandType; 7 | import org.apache.ibatis.reflection.TypeParameterResolver; 8 | import org.apache.ibatis.session.Configuration; 9 | 10 | import java.lang.reflect.Method; 11 | import java.lang.reflect.ParameterizedType; 12 | import java.lang.reflect.Type; 13 | import java.util.*; 14 | 15 | /** 16 | * 提供configuration中数据的通用查询功能的类 17 | * 18 | * @author sobann 19 | */ 20 | public abstract class ConfigurationSupport implements DevBaseConstant { 21 | 22 | /** 23 | * MappedStatement 从configuration中获取 24 | * 25 | * @param mapperInterface 26 | * @param methodName 27 | * @param declaringClass 28 | * @param configuration 29 | * @return 30 | */ 31 | protected MappedStatement resolveMappedStatement(Class mapperInterface, String methodName, Class declaringClass, Configuration configuration) { 32 | //通过mapperInterface.code确认唯一的MappedStatement 33 | String statementId = String.format(MAPPED_STATEMENT_ID_TEMPLATE, mapperInterface.getName(), methodName); 34 | if (configuration.hasStatement(statementId)) { 35 | return configuration.getMappedStatement(statementId); 36 | } else if (mapperInterface.equals(declaringClass)) { 37 | throw new StatementNotFoundException(statementId); 38 | } 39 | 40 | for (Class superInterface : mapperInterface.getInterfaces()) { 41 | if (declaringClass.isAssignableFrom(superInterface)) { 42 | MappedStatement ms = resolveMappedStatement(superInterface, methodName, declaringClass, configuration); 43 | if (ms != null) { 44 | return ms; 45 | } 46 | } 47 | } 48 | throw new StatementNotFoundException(statementId); 49 | } 50 | 51 | 52 | /** 53 | * returnType从配置的resultMap中获取,默认为Map 54 | * 55 | * @param mappedStatement 56 | * @return 57 | */ 58 | protected Class getResultMapClassType(MappedStatement mappedStatement) { 59 | Class type; 60 | try { 61 | List resultMaps = mappedStatement.getResultMaps(); 62 | if (resultMaps.size() == ONE) { 63 | type = resultMaps.get(ZERO).getType(); 64 | } else { 65 | type = resultMaps.get(resultMaps.size() - ONE).getType(); 66 | } 67 | } catch (Exception e) { 68 | type = Map.class; 69 | } 70 | return type; 71 | } 72 | 73 | /** 74 | * 解析返回数据类型 75 | * 需要根据增删改方法确认的情况 76 | * 77 | * @param mappedStatement 78 | * @return 79 | */ 80 | protected Class resolveReturnType(MappedStatement mappedStatement) { 81 | //根据方法返回值获取类型 82 | SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); 83 | switch (sqlCommandType) { 84 | case INSERT: 85 | case UPDATE: 86 | case DELETE: 87 | return Integer.class; 88 | case SELECT: 89 | return List.class; 90 | } 91 | return null; 92 | } 93 | 94 | /** 95 | * 解析返回数据类型 96 | * 97 | * @param method 98 | * @param srcType 99 | * @return 100 | */ 101 | protected Class resolveReturnType(Method method, Type srcType) { 102 | //根据方法返回值获取类型 103 | try { 104 | Class returnType; 105 | Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, srcType); 106 | if (resolvedReturnType instanceof Class) { 107 | returnType = (Class) resolvedReturnType; 108 | } else if (resolvedReturnType instanceof ParameterizedType) { 109 | returnType = (Class) ((ParameterizedType) resolvedReturnType).getRawType(); 110 | } else { 111 | returnType = method.getReturnType(); 112 | } 113 | return returnType; 114 | } catch (Exception e) { 115 | //解析失败返回null 116 | return null; 117 | } 118 | } 119 | 120 | /** 121 | * 是否需要将查询结果包装一次 122 | * 123 | * @param method 124 | */ 125 | protected boolean resolveNeedWrapperResult(Method method) { 126 | return Arrays.stream(DEFAULT_WRAPPER_RESULT_METHOD_NAMES).anyMatch(item -> Objects.equals(item, method.getName())); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/support/DevBaseConstant.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.support; 2 | 3 | /** 4 | * 一些常量配置 5 | * FIXME 与sql相关的内容需要从此处移出,根据具体的语义环境获取对应的meta sql 6 | * 7 | * @author sobann 8 | */ 9 | public interface DevBaseConstant { 10 | String MAPPED_STATEMENT_ID_TEMPLATE = "%s.%s"; 11 | String BLANK_STR = ""; 12 | String SQL_ALL = "*"; 13 | String ACTION_EW = "ew"; 14 | String[] DEFAULT_WRAPPER_RESULT_METHOD_NAMES = new String[]{"doAction"}; 15 | String WRAPPER_RESULT_KEY = "result"; 16 | String SCRIPT_TAG_TEMPLATE = ""; 17 | String DEFAULT_SQL_CONFIG_DATASOURCE = "sys"; 18 | String DEFAULT_SQL_CONFIG_CODE = "SYS_SQL_CONFIG"; 19 | String DEFAULT_MYSQL_SYS_CONFIG_SQL = "SELECT id, code AS code, dbKey AS dbkey, actiontype AS sqlCommandTypeCode, content AS content FROM sys_sql_config WHERE actiontype IN (0,1,2,3,4) AND code = #{ew.param.code}"; 20 | String TOKEN_SEPARATOR = "#"; 21 | 22 | String ALL_IDENTIFIER = "*"; 23 | String DEFAULT_TABLE_META_CONFIG_CODE = "table_meta"; 24 | String DEFAULT_MYSQL_TABLE_META_CONFIG_SQL = "SELECT table_schema AS tableSchema, table_name AS tableName, column_name AS columnName, column_key AS columnKey, data_type As dataType FROM information_schema.columns AND table_schema = #{ew.param.table_schema} AND table_name = #{ew.param.table_name} "; 25 | String TABLE_SCHEMA_KEY = "table_schema"; 26 | String TABLE_NAME_KEY = "table_name"; 27 | int ZERO = 0; 28 | int ONE = 1; 29 | int TWO = 2; 30 | int THREE = 3; 31 | int TEN = 10; 32 | int DEFAULT_CURRENT = ZERO; 33 | int DEFAULT_SIZE = TEN; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/wrapper/BeanWrapperResult.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.wrapper; 2 | 3 | import com.cheese.db.core.exception.ResultWrapperException; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * 使用实例方式进行包装 10 | * 11 | * @param 包装返回的实体类型 12 | * @param 被包装的最终数据 13 | * 14 | * @author sobann 15 | */ 16 | public class BeanWrapperResult implements WrapperResult, DevBaseConstant { 17 | 18 | private Field resultFiled; 19 | private final Class beanClass; 20 | private final T bean; 21 | 22 | public BeanWrapperResult(Class beanClass) { 23 | try { 24 | this.beanClass = beanClass; 25 | //必须提供一个空参的构造方法以及针对result的getSet方法 26 | this.bean = beanClass.newInstance(); 27 | this.resultFiled = beanClass.getDeclaredField(WRAPPER_RESULT_KEY); 28 | resultFiled.setAccessible(true); 29 | } catch (Exception e) { 30 | throw new ResultWrapperException(e.getMessage()); 31 | } 32 | } 33 | 34 | @Override 35 | public WrapperResult wrapperResult(R result) { 36 | //设置属性 37 | try { 38 | resultFiled.set(bean, result); 39 | return this; 40 | } catch (Exception e) { 41 | throw new ResultWrapperException(e.getMessage()); 42 | } 43 | } 44 | 45 | @Override 46 | public R getResult() { 47 | //设置属性 48 | try { 49 | R result = (R) resultFiled.get(bean); 50 | return result; 51 | } catch (Exception e) { 52 | throw new ResultWrapperException(e.getMessage()); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/wrapper/MapWrapperResult.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.wrapper; 2 | 3 | import com.cheese.db.core.support.DevBaseConstant; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 返回值包装类,默认使用map进行包装 10 | * 11 | * @author sobann 12 | */ 13 | public class MapWrapperResult implements WrapperResult, R>, DevBaseConstant { 14 | 15 | private MapWrapperResult() { 16 | } 17 | 18 | private final Map wrapper = new HashMap<>(); 19 | 20 | @Override 21 | public WrapperResult, R> wrapperResult(R result) { 22 | this.wrapper.put(WRAPPER_RESULT_KEY, result); 23 | return this; 24 | } 25 | 26 | @Override 27 | public R getResult() { 28 | return wrapper.get(WRAPPER_RESULT_KEY); 29 | } 30 | 31 | public static class Builder { 32 | private static MapWrapperResult wrapperResult = new MapWrapperResult(); 33 | 34 | public static MapWrapperResult build() { 35 | return Builder.wrapperResult; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cheese-db-core/src/main/java/com/cheese/db/core/wrapper/WrapperResult.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.core.wrapper; 2 | 3 | /** 4 | * 包装类顶层接口 5 | * 6 | * @param 包装返回的实体类型 7 | * @param 被包装的最终数据 8 | */ 9 | public interface WrapperResult { 10 | 11 | /** 12 | * 获取包装对象,传入result数据进行包装 13 | * 14 | * @param result 15 | * @return 16 | */ 17 | WrapperResult wrapperResult(R result); 18 | 19 | /** 20 | * 获取包装对象中存放的数据 21 | * 22 | * @return 23 | */ 24 | R getResult(); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /cheese-db-rpc/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheese.db 8 | cheese-db-rpc 9 | 1.0.0 10 | the components which can use rpc extend 11 | 12 | 13 | 2.9.9 14 | 4.0.63 15 | 16 | 17 | 18 | 19 | 20 | com.fasterxml.jackson.core 21 | jackson-databind 22 | ${jackson.version} 23 | true 24 | 25 | 26 | 27 | com.caucho 28 | hessian 29 | ${hessian.version} 30 | 31 | 32 | 33 | com.cheese.db 34 | cheese-db-core 35 | ${project.version} 36 | 37 | 38 | -------------------------------------------------------------------------------- /cheese-db-sample/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheese.db 8 | cheese-db-sample 9 | 1.0.0 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 2.1.6.RELEASE 15 | 16 | 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter 23 | 24 | 25 | 26 | mysql 27 | mysql-connector-java 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-test 33 | test 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-web 38 | 39 | 40 | com.cheese.db 41 | cheese-db-spring-boot-starter 42 | 1.0.0 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /cheese-db-sample/src/main/java/com/cheese/db/sample/CheeseSampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.sample; 2 | 3 | import com.cheese.db.autoconfigure.EnableDevBase; 4 | import com.cheese.db.core.condition.Action; 5 | import com.cheese.db.core.condition.manager.DevBaseActionManager; 6 | import com.cheese.db.core.condition.simple.insert.InsertTableAction; 7 | import com.cheese.db.core.mapper.DB; 8 | import com.cheese.db.sample.service.ICommonService; 9 | import com.cheese.db.spring.injector.collector.dialect.MysqlDialectCollector; 10 | import org.springframework.boot.CommandLineRunner; 11 | import org.springframework.boot.SpringApplication; 12 | import org.springframework.boot.autoconfigure.SpringBootApplication; 13 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 14 | import org.springframework.context.annotation.Bean; 15 | 16 | import javax.annotation.Resource; 17 | import java.util.Date; 18 | 19 | /** 20 | * devbase功能可以兼容DataSourceAutoConfiguration的功能,进行相应的配置即可 21 | * 22 | * @author sobann 23 | */ 24 | @EnableDevBase 25 | @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 26 | public class CheeseSampleApplication implements CommandLineRunner { 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(CheeseSampleApplication.class, args); 30 | } 31 | 32 | @Resource 33 | private DB db; 34 | @Resource 35 | private ICommonService commonService; 36 | 37 | @Override 38 | public void run(String... args) throws Exception { 39 | // 数据测试移动到ut中参考 CheeseApplicationTest 40 | } 41 | 42 | @Bean 43 | public MysqlDialectCollector mysqlDialectCollector() { 44 | return new MysqlDialectCollector(); 45 | } 46 | 47 | 48 | @Bean 49 | public DevBaseActionManager devBaseActionManager() { 50 | DevBaseActionManager devBaseActionManager = new DevBaseActionManager() { 51 | @Override 52 | public void manager(Action action) { 53 | if (action instanceof InsertTableAction) { 54 | InsertTableAction insertAction = (InsertTableAction) action; 55 | insertAction.putData("create_by", 50); 56 | insertAction.putData("create_time", new Date()); 57 | System.out.println("custom devBaseActionManager running"); 58 | } 59 | } 60 | }; 61 | return devBaseActionManager; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cheese-db-sample/src/main/java/com/cheese/db/sample/service/ICommonService.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.sample.service; 2 | 3 | /** 4 | * 业务测试 5 | * 6 | * @author sobann 7 | */ 8 | public interface ICommonService { 9 | 10 | void useTransaction(); 11 | } 12 | -------------------------------------------------------------------------------- /cheese-db-sample/src/main/java/com/cheese/db/sample/service/impl/CommonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.sample.service.impl; 2 | 3 | import com.cheese.db.core.condition.Actions; 4 | import com.cheese.db.core.condition.load.LoadAction; 5 | import com.cheese.db.core.mapper.DB; 6 | import com.cheese.db.sample.service.ICommonService; 7 | import com.cheese.db.spring.annotation.DevBaseMultiDataSourceTransactional; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * 测试业务 12 | * 13 | * @author sobann 14 | */ 15 | @Service("commonService") 16 | public class CommonServiceImpl implements ICommonService { 17 | 18 | private final DB db; 19 | 20 | public CommonServiceImpl(DB db){ 21 | this.db = db; 22 | } 23 | 24 | @DevBaseMultiDataSourceTransactional(transactionDbKeys = {"sys", "bus"}) 25 | @Override 26 | public void useTransaction() { 27 | LoadAction action = Actions.getLoad("sys", "INSERT_NEW_SYS_USER"); 28 | action.putData("name", "cheese679"); 29 | action.putData("full_name", "cheese-repository"); 30 | action.putData("nick_name", "cheese1ne"); 31 | action.putData("email", "cheese@163.com"); 32 | action.putData("telephone", "13377778888"); 33 | action.putData("password", "cheese1'spassword"); 34 | action.putData("status", 1); 35 | action.putData("create_by", 50); 36 | action.putData("remark", "无"); 37 | db.doAction(action); 38 | 39 | action = Actions.getLoad("bus", "UPDATE_BORROW_APPLY_DATA"); 40 | action.putParam("id", 1); 41 | action.putData("status", 1); 42 | db.doAction(action); 43 | throw new RuntimeException("rollback transaction"); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cheese-db-sample/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8081 2 | logging.level.com.cheese.db.spring=debug 3 | spring.main.allow-bean-definition-overriding=true 4 | 5 | # devbase 配置 6 | ## devbase-db开启开关,默认开启 7 | devbase-db.enabled=true 8 | ## devbase-db使用默认配置,默认为false 9 | devbase-db.use-default-config=true 10 | ## 事务配置 11 | devbase-db.transaction-type=advisor 12 | 13 | # 多数据源配置 14 | devbase-db.configuration.sys.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl 15 | devbase-db.configuration.sys.insert-key-property=id 16 | devbase-db.configuration.bus.insert-key-property=id 17 | 18 | ## 配置数据源 19 | devbase-db.config-data-source=sys 20 | ## 加载数据库的元数据,为数据库下的所有表生成基础增删改的方法 21 | ## 元数据加载的key 22 | devbase-db.data-sources.sys.scheme-key=sys 23 | ## 元数据加载数据库的名称,与url中的数据库名一致 24 | devbase-db.data-sources.sys.scheme-name=db_sys 25 | devbase-db.data-sources.sys.datasource-type=com.alibaba.druid.pool.DruidDataSource 26 | devbase-db.data-sources.sys.url=jdbc:mysql://localhost:3306/db_sys?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 27 | devbase-db.data-sources.sys.driver-class-name=com.mysql.cj.jdbc.Driver 28 | devbase-db.data-sources.sys.username=root 29 | devbase-db.data-sources.sys.password=root 30 | 31 | ## 其他数据源 可以配置多个 32 | devbase-db.data-sources.bus.scheme-key=bus 33 | devbase-db.data-sources.bus.scheme-name=db_bus 34 | devbase-db.data-sources.bus.datasource-type=com.alibaba.druid.pool.DruidDataSource 35 | devbase-db.data-sources.bus.url=jdbc:mysql://localhost:3306/db_bus?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 36 | devbase-db.data-sources.bus.driver-class-name=com.mysql.cj.jdbc.Driver 37 | devbase-db.data-sources.bus.username=root 38 | devbase-db.data-sources.bus.password=root 39 | -------------------------------------------------------------------------------- /cheese-db-sample/src/main/resources/config/db.setting: -------------------------------------------------------------------------------- 1 | [sys] 2 | url = jdbc:mysql://localhost:3306/tms1cd_design?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 3 | username = root 4 | password = root 5 | autoCommit = true 6 | connectionTimeout = 60000 7 | idleTimeout = 60000 8 | maxLifetime = 120000 9 | validationTimeout=3000 10 | connectionTestQuery = SELECT 1 11 | minimumIdle = 10 12 | maximumPoolSize = 50 13 | readOnly = false 14 | 15 | 16 | [bus] 17 | url = jdbc:mysql://localhost:3306/hb_databank?characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8 18 | username = root 19 | password = root 20 | autoCommit = true 21 | connectionTimeout = 60000 22 | idleTimeout = 60000 23 | maxLifetime = 120000 24 | validationTimeout=3000 25 | connectionTestQuery = SELECT 1 26 | minimumIdle = 10 27 | maximumPoolSize = 50 28 | readOnly = false -------------------------------------------------------------------------------- /cheese-db-sample/src/test/java/com/cheese/db/sample/test/CheeseApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.sample.test; 2 | 3 | import com.cheese.db.core.condition.Actions; 4 | import com.cheese.db.core.condition.load.LoadAction; 5 | import com.cheese.db.core.condition.simple.delete.DeleteTableAction; 6 | import com.cheese.db.core.condition.simple.insert.InsertTableAction; 7 | import com.cheese.db.core.condition.simple.query.QueryTableAction; 8 | import com.cheese.db.core.condition.simple.update.UpdateTableAction; 9 | import com.cheese.db.core.enums.Comparator; 10 | import com.cheese.db.core.enums.LikeType; 11 | import com.cheese.db.core.enums.RangeType; 12 | import com.cheese.db.core.mapper.DB; 13 | import com.cheese.db.sample.service.ICommonService; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.springframework.boot.test.context.SpringBootTest; 17 | import org.springframework.context.annotation.Profile; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | import javax.annotation.Resource; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.stream.Stream; 24 | 25 | /** 26 | * cheese action简单的单元测试 27 | * 28 | * @author sobann 29 | */ 30 | @Profile("test") 31 | @SpringBootTest 32 | @RunWith(SpringRunner.class) 33 | public class CheeseApplicationTest { 34 | 35 | 36 | @Resource 37 | private DB db; 38 | @Resource 39 | private ICommonService commonService; 40 | 41 | /** 42 | * 单表新增 43 | */ 44 | @Test 45 | public void insertTest() { 46 | // 新增 47 | InsertTableAction insertAction = new InsertTableAction("bus", "dt_borrow_manage_borrow_apply"); 48 | insertAction.putData("type", "offline"); 49 | insertAction.putData("apply_code", "TOF-20230103-010"); 50 | insertAction.putData("geodata_id", "10010"); 51 | insertAction.putData("apply_user", "50"); 52 | insertAction.putData("apply_reason", "这是什么 申请一下"); 53 | insertAction.putData("status", 0); 54 | insertAction.putData("is_deleted", 0); 55 | insertAction.putData("remark", "无"); 56 | db.doAction(insertAction); 57 | // 获取自增主键 需要设置数据库表自增,后续可以借助DevBaseActionManager使用雪花id,主键column目前只能精确到数据库配置 devbase-db.configuration.${dbKey}.insert-key-property=id,无法精确配置到表(由于无实体配置) 58 | Long id = insertAction.getId(); 59 | System.out.println("id = " + id); 60 | } 61 | 62 | /** 63 | * 单表查询 64 | */ 65 | @Test 66 | public void selectTest() { 67 | QueryTableAction queryAction = new QueryTableAction("bus", "dt_borrow_manage_borrow_apply"); 68 | // 范围查询 69 | queryAction.putComparatorParam("create_time", Comparator.GTE, "2020-01-01 00:00:00"); 70 | queryAction.putComparatorParam("create_time", Comparator.LTE, "2023-12-31 23:59:59"); 71 | // 范围查询,有索引时数值明确时建议使用 IN 72 | // queryAction.putRangeParam("id", RangeType.IN, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97); 73 | queryAction.putRangeParam("apply_user", RangeType.IN, 1, 50, 51); 74 | // 简单条件 putParam 或者 putRangeParam 使用 Comparator.EQUALS 以下两种方法等价 75 | queryAction.putParam("remark", "无"); 76 | queryAction.putComparatorParam("remark", Comparator.EQUALS, "无"); 77 | // 模糊条件 78 | queryAction.putLikeParam("apply_code", LikeType.ALL, "TOF"); 79 | List> maps = db.doActionGetList(queryAction); 80 | 81 | System.out.println("maps.size = " + maps.size()); 82 | } 83 | 84 | /** 85 | * 单表删除 86 | */ 87 | @Test 88 | public void deleteTest() { 89 | // 删除 删除api于查询基本一致 90 | DeleteTableAction deleteAction = new DeleteTableAction("bus", "dt_borrow_manage_borrow_apply"); 91 | // 范围条件 range 92 | deleteAction.putComparatorParam("create_time", Comparator.GTE, "2021-01-01 00:00:00"); 93 | deleteAction.putComparatorParam("create_time", Comparator.LTE, "2023-12-31 23:59:59"); 94 | // 范围条件,有索引时数值明确时建议使用 IN 95 | deleteAction.putRangeParam("id", RangeType.IN, Stream.iterate(40, item-> item + 1).limit(60).toArray()); 96 | // 简单条件 putParam 或者 putRangeCdn 使用 Comparator.EQUALS 以下两种方法等价 97 | deleteAction.putParam("is_deleted", 1); 98 | deleteAction.putComparatorParam("is_deleted", Comparator.EQUALS, 1); 99 | // 模糊条件 100 | deleteAction.putLikeParam("apply_code", LikeType.ALL, "TOF"); 101 | db.doAction(deleteAction); 102 | } 103 | 104 | /** 105 | * 单表修改 106 | */ 107 | @Test 108 | public void updateTest() { 109 | // 修改,条件设置与查询、删除基本一致,设置数据使用putData 110 | UpdateTableAction updateAction = new UpdateTableAction("bus", "dt_borrow_manage_borrow_apply"); 111 | // 范围条件 112 | updateAction.putComparatorParam("create_time", Comparator.GTE, "2021-01-01 00:00:00"); 113 | updateAction.putComparatorParam("create_time", Comparator.LTE, "2023-12-31 23:59:59"); 114 | // 范围条件,但 NOT IN 不建议使用哦 115 | updateAction.putRangeParam("id", RangeType.NOT_IN, 1, 2, 3); 116 | // 简单条件 117 | updateAction.putParam("is_deleted", 0); 118 | updateAction.putComparatorParam("status", Comparator.NOT_EQUALS, 1); 119 | // 模糊条件 120 | updateAction.putLikeParam("apply_code", LikeType.ALL, "TOF"); 121 | 122 | // 设置数据 123 | updateAction.putData("is_deleted", 1); 124 | updateAction.putData("apply_reason", "是资料啊 那就申请吧"); 125 | db.doAction(updateAction); 126 | } 127 | 128 | /** 129 | * 联表查询或者其他复杂增删改操作 定义在数据库中的mybatis脚本 130 | */ 131 | @Test 132 | public void loadTest() { 133 | LoadAction loadAction = Actions.getLoad("bus", "LOAD_BORROW_APPLY_INFO"); 134 | loadAction.putParam("apply_id", 1); 135 | loadAction.putParam("is_deleted", 0); 136 | Map taskInfo = db.doActionGetOne(loadAction); 137 | System.out.println("applyInfo = " + taskInfo); 138 | } 139 | 140 | @Test 141 | public void transactionTest() { 142 | commonService.useTransaction(); 143 | } 144 | 145 | 146 | } 147 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheese.db 8 | cheese-db-spring-boot-starter 9 | 1.0.0 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | com.cheese.db 19 | cheese-db-spring 20 | ${project.version} 21 | compile 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-autoconfigure 26 | compile 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-jdbc 31 | compile 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-autoconfigure-processor 36 | compile 37 | true 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-configuration-processor 42 | compile 43 | true 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter 49 | provided 50 | 51 | 52 | 53 | com.github.pagehelper 54 | pagehelper 55 | 5.1.11 56 | provided 57 | 58 | 59 | 60 | com.alibaba 61 | druid 62 | 1.1.10 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-dependencies 73 | 2.1.4.RELEASE 74 | pom 75 | import 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | org.apache.maven.plugins 84 | maven-source-plugin 85 | 86 | true 87 | 88 | 89 | 90 | attach-sources 91 | compile 92 | 93 | jar 94 | 95 | 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-deploy-plugin 101 | 2.8.1 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/src/main/java/com/cheese/db/autoconfigure/DevBaseDbAutoImportSelector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.autoconfigure; 2 | 3 | import com.cheese.db.enums.TransactionEnum; 4 | import org.springframework.context.EnvironmentAware; 5 | import org.springframework.context.annotation.ImportSelector; 6 | import org.springframework.core.env.Environment; 7 | import org.springframework.core.type.AnnotationMetadata; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * 这里配置一些组件中提供选择的bean实例 14 | * 例如事务 aspectj 和 aop 二选一 15 | * 16 | * @author sobann 17 | */ 18 | public class DevBaseDbAutoImportSelector implements ImportSelector, EnvironmentAware { 19 | 20 | public static final String TRANSACTION = "devbase-db.transaction-type"; 21 | 22 | private Environment environment; 23 | 24 | @Override 25 | public String[] selectImports(AnnotationMetadata annotationMetadata) { 26 | List configurations = new ArrayList<>(); 27 | String transactionProps = environment.getProperty(TRANSACTION, "default"); 28 | String transactionType = TransactionEnum.parseType(transactionProps); 29 | configurations.add(transactionType); 30 | return configurations.toArray(new String[0]); 31 | } 32 | 33 | @Override 34 | public void setEnvironment(Environment environment) { 35 | this.environment = environment; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/src/main/java/com/cheese/db/autoconfigure/EnableDevBase.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.autoconfigure; 2 | 3 | import org.springframework.context.annotation.Import; 4 | 5 | import java.lang.annotation.ElementType; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * 复合注解,目前仅用于DevBaseDB的装配 12 | * 加入此注解后,默认扫描全部自动装配类,具体配置的开关请参考相关配置类 13 | * 14 | * @author sobann 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.TYPE) 18 | @Import({DevBaseDBAutoConfiguration.class, DevBaseDbAutoImportSelector.class}) 19 | public @interface EnableDevBase { 20 | } 21 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/src/main/java/com/cheese/db/enums/TransactionEnum.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.enums; 2 | 3 | /** 4 | * 事务方式枚举 5 | * 6 | * @author sobann 7 | */ 8 | public enum TransactionEnum { 9 | 10 | /** 11 | * 默认的事务拦截方式 使用aspectj 12 | */ 13 | DEFAULT("default", "com.cheese.db.spring.transaction.aspectj.DevBaseMultiDataSourceTransactionalAspect"), 14 | 15 | /** 16 | * aspectj的事务拦截方式,比较灵活 17 | */ 18 | ASPECTJ("aspectj", "com.cheese.db.spring.transaction.aspectj.DevBaseMultiDataSourceTransactionalAspect"), 19 | 20 | /** 21 | * advisor事务的拦截方式 22 | */ 23 | ADVISOR("advisor", "com.cheese.db.spring.transaction.aop.DevBaseMultiDatasourceTransactionAdvisor"); 24 | 25 | 26 | TransactionEnum(String type, String fullClassName) { 27 | this.type = type; 28 | this.fullClassName = fullClassName; 29 | } 30 | 31 | private final String type; 32 | private final String fullClassName; 33 | 34 | public String getFullClassName() { 35 | return this.fullClassName; 36 | } 37 | 38 | public String getType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 根据transactionType类型获取全类名 44 | * 45 | * @param type 46 | * @return 47 | */ 48 | public static String parseType(String type) { 49 | TransactionEnum[] values = TransactionEnum.values(); 50 | for (TransactionEnum selectorEnum : values) { 51 | if (selectorEnum.type.equalsIgnoreCase(type)) { 52 | return selectorEnum.getFullClassName(); 53 | } 54 | } 55 | throw new IllegalArgumentException("unknown transaction type:" + type); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/src/main/java/com/cheese/db/props/DevBaseDBProps.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.props; 2 | 3 | import com.cheese.db.core.props.DataSourceConfig; 4 | import com.cheese.db.core.props.MybatisConfig; 5 | import com.cheese.db.enums.TransactionEnum; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * devbase-db环境配置项 12 | * 13 | * @author sobann 14 | */ 15 | @ConfigurationProperties(prefix = "devbase-db") 16 | public class DevBaseDBProps { 17 | 18 | private boolean enabled = true; 19 | 20 | private boolean useDefaultConfig = false; 21 | 22 | private boolean usePageHelper = true; 23 | 24 | private String configDataSource; 25 | 26 | private TransactionEnum transactionType; 27 | 28 | /** 29 | * 多数据源下的mybatis配置信息 30 | */ 31 | private Map configuration; 32 | 33 | /** 34 | * 多数据源的连接配置 35 | */ 36 | private Map dataSources; 37 | 38 | public boolean isEnabled() { 39 | return enabled; 40 | } 41 | 42 | public void setEnabled(boolean enabled) { 43 | this.enabled = enabled; 44 | } 45 | 46 | public boolean isUseDefaultConfig() { 47 | return useDefaultConfig; 48 | } 49 | 50 | public void setUseDefaultConfig(boolean useDefaultConfig) { 51 | this.useDefaultConfig = useDefaultConfig; 52 | } 53 | 54 | public Map getConfiguration() { 55 | return configuration; 56 | } 57 | 58 | public void setConfiguration(Map configuration) { 59 | this.configuration = configuration; 60 | } 61 | 62 | public boolean isUsePageHelper() { 63 | return usePageHelper; 64 | } 65 | 66 | public void setUsePageHelper(boolean usePageHelper) { 67 | this.usePageHelper = usePageHelper; 68 | } 69 | 70 | public String getConfigDataSource() { 71 | return configDataSource; 72 | } 73 | 74 | public void setConfigDataSource(String configDataSource) { 75 | this.configDataSource = configDataSource; 76 | } 77 | 78 | public Map getDataSources() { 79 | return dataSources; 80 | } 81 | 82 | public void setDataSources(Map dataSources) { 83 | this.dataSources = dataSources; 84 | } 85 | 86 | public TransactionEnum getTransactionType() { 87 | return transactionType; 88 | } 89 | 90 | public void setTransactionType(TransactionEnum transactionType) { 91 | this.transactionType = transactionType; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /cheese-db-spring-boot-starter/src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "devbase-db.enabled", 5 | "type": "java.lang.Boolean", 6 | "description": "Whether to use devbase.", 7 | "sourceType": "com.cheese.db.props.DevBaseDBProps", 8 | "defaultValue": true 9 | }, 10 | { 11 | "name": "devbase-db.use-default-config", 12 | "type": "java.lang.Boolean", 13 | "description": "Whether to use devbase default config.", 14 | "sourceType": "com.cheese.db.props.DevBaseDBProps", 15 | "defaultValue": false 16 | }, 17 | { 18 | "name": "devbase-db.use-page-helper", 19 | "type": "java.lang.Boolean", 20 | "description": "Whether to use pageHelper", 21 | "sourceType": "com.cheese.db.props.DevBaseDBProps", 22 | "defaultValue": true 23 | }, 24 | { 25 | "name": "devbase-db.config-data-source", 26 | "type": "java.lang.String", 27 | "description": "Load config-sql's dbKey", 28 | "sourceType": "com.cheese.db.props.DevBaseDBProps" 29 | }, 30 | { 31 | "name": "devbase-db.transaction-type", 32 | "type": "com.cheese.db.enums.TransactionEnum", 33 | "description": "choose a transaction type for devbase", 34 | "sourceType": "com.cheese.db.props.DevBaseDBProps" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /cheese-db-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheese.db 8 | cheese-db-spring 9 | 1.0.0 10 | 11 | 12 | 8 13 | 8 14 | 15 | 16 | 17 | 18 | com.cheese.db 19 | cheese-db-core 20 | ${project.version} 21 | 22 | 23 | org.mybatis 24 | mybatis-spring 25 | 2.0.2 26 | compile 27 | 28 | 29 | org.springframework 30 | spring-core 31 | 5.1.8.RELEASE 32 | provided 33 | 34 | 35 | org.springframework 36 | spring-context 37 | 5.1.8.RELEASE 38 | provided 39 | 40 | 41 | org.springframework 42 | spring-jdbc 43 | 5.1.8.RELEASE 44 | provided 45 | 46 | 47 | org.springframework 48 | spring-tx 49 | 5.1.8.RELEASE 50 | provided 51 | 52 | 53 | 54 | cn.hutool 55 | hutool-all 56 | 4.6.1 57 | compile 58 | 59 | 60 | 61 | org.aspectj 62 | aspectjweaver 63 | 1.9.4 64 | compile 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-source-plugin 73 | 74 | true 75 | 76 | 77 | 78 | attach-sources 79 | compile 80 | 81 | jar 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-deploy-plugin 89 | 2.8.1 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/annotation/DevBaseMapperRegistrar.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.annotation; 2 | 3 | 4 | import com.cheese.db.spring.mapper.DevBaseMapperFactoryBean; 5 | import com.cheese.db.spring.mapper.DevBaseMapperScannerConfigurer; 6 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 7 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 8 | import org.springframework.context.ResourceLoaderAware; 9 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 10 | import org.springframework.core.annotation.AnnotationAttributes; 11 | import org.springframework.core.io.ResourceLoader; 12 | import org.springframework.core.type.AnnotationMetadata; 13 | import org.springframework.util.ClassUtils; 14 | import org.springframework.util.StringUtils; 15 | 16 | import java.lang.annotation.Annotation; 17 | import java.util.Arrays; 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | 21 | /** 22 | * DevBaseMappers注解配置元数据注册器 23 | *

24 | * 通过DevBaseMapperScannerConfigurer包扫描器完成 25 | * devbase 持久层接口的beanDefinition的创建 26 | * 27 | * @author sobann 28 | */ 29 | public class DevBaseMapperRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { 30 | 31 | private ResourceLoader resourceLoader; 32 | 33 | @Override 34 | public void setResourceLoader(ResourceLoader resourceLoader) { 35 | this.resourceLoader = resourceLoader; 36 | } 37 | 38 | @Override 39 | public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { 40 | AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(annotationMetadata.getAnnotationAttributes(DevBaseMappers.class.getName())); 41 | if (mapperScanAttrs != null) { 42 | this.registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(annotationMetadata, 0)); 43 | } 44 | } 45 | 46 | void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) { 47 | BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(DevBaseMapperScannerConfigurer.class); 48 | 49 | //beanDefinition属性填充 50 | builder.addPropertyValue("processPropertyPlaceHolders", true); 51 | 52 | Class annotationClass = annoAttrs.getClass("annotationClass"); 53 | if (!Annotation.class.equals(annotationClass)) { 54 | builder.addPropertyValue("annotationClass", annotationClass); 55 | } 56 | 57 | Class markerInterface = annoAttrs.getClass("markerInterface"); 58 | if (!Class.class.equals(markerInterface)) { 59 | builder.addPropertyValue("markerInterface", markerInterface); 60 | } 61 | 62 | Class mapperFactoryBeanClass = annoAttrs.getClass("factoryBean"); 63 | if (!DevBaseMapperFactoryBean.class.equals(mapperFactoryBeanClass)) { 64 | builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass); 65 | } 66 | 67 | //devSqlSessionTemplatesRef 68 | String sqlSessionTemplateRef = annoAttrs.getString("devBaseSqlSessionTemplates"); 69 | if (StringUtils.hasText(sqlSessionTemplateRef)) { 70 | builder.addPropertyValue("devBaseSqlSessionTemplatesBeanName", annoAttrs.getString("devBaseSqlSessionTemplates")); 71 | } 72 | 73 | //devBaseSqlInjectorsRef 74 | String devBaseSqlInjectorsRef = annoAttrs.getString("devBaseSqlInjectors"); 75 | if (StringUtils.hasText(devBaseSqlInjectorsRef)) { 76 | builder.addPropertyValue("devBaseSqlInjectorsBeanName", annoAttrs.getString("devBaseSqlInjectors")); 77 | } 78 | 79 | //devBaseActionCheckers 80 | String devBaseActionCheckersRef = annoAttrs.getString("devBaseActionManager"); 81 | if (StringUtils.hasText(devBaseActionCheckersRef)) { 82 | builder.addPropertyValue("devBaseActionManagerBeanName", annoAttrs.getString("devBaseActionManager")); 83 | } 84 | 85 | List basePackages = Arrays.stream(annoAttrs.getClassArray("mapperClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()); 86 | String lazyInitialization = annoAttrs.getString("lazyInitialization"); 87 | if (StringUtils.hasText(lazyInitialization)) { 88 | builder.addPropertyValue("lazyInitialization", lazyInitialization); 89 | } 90 | 91 | builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); 92 | registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); 93 | } 94 | 95 | private static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) { 96 | return importingClassMetadata.getClassName() + "#" + DevBaseMapperRegistrar.class.getSimpleName() + "#" + index; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/annotation/DevBaseMappers.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.annotation; 2 | 3 | import com.cheese.db.core.mapper.DB; 4 | import com.cheese.db.spring.mapper.DevBaseMapperFactoryBean; 5 | import org.springframework.context.annotation.Import; 6 | 7 | import java.lang.annotation.*; 8 | 9 | /** 10 | * 参考@MapperScanner 11 | * 12 | * @author sobann 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ElementType.TYPE}) 16 | @Import({DevBaseMapperRegistrar.class}) 17 | @Documented 18 | public @interface DevBaseMappers { 19 | 20 | Class[] mapperClasses() default {DB.class}; 21 | 22 | Class annotationClass() default Annotation.class; 23 | 24 | Class markerInterface() default Class.class; 25 | 26 | Class factoryBean() default DevBaseMapperFactoryBean.class; 27 | 28 | String lazyInitialization() default ""; 29 | 30 | String devBaseSqlSessionTemplates() default ""; 31 | 32 | String devBaseSqlInjectors() default ""; 33 | 34 | String devBaseActionManager() default ""; 35 | } 36 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/annotation/DevBaseMultiDataSourceTransactional.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.annotation; 2 | 3 | 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 多数据源的事务管理 11 | * 多数据源配置的管理分布式事务管理,利用代码+切面实现 12 | * 13 | * @author sobann 14 | */ 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Target(value = { ElementType.METHOD, ElementType.TYPE}) 17 | public @interface DevBaseMultiDataSourceTransactional { 18 | 19 | /** 20 | * 需要进行事务管理的数据库标识 21 | */ 22 | String[] transactionDbKeys() default {}; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/datasource/DatasourceContext.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.datasource; 2 | 3 | import com.cheese.db.core.props.DataSourceConfig; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 数据源上下文的内容,包装DataSourceConfig 9 | * 10 | * @author sobann 11 | */ 12 | public class DatasourceContext { 13 | 14 | private String configDataSource; 15 | 16 | private Map dataSources; 17 | 18 | public String getConfigDataSource() { 19 | return configDataSource; 20 | } 21 | 22 | public void setConfigDataSource(String configDataSource) { 23 | this.configDataSource = configDataSource; 24 | } 25 | 26 | public Map getDataSources() { 27 | return dataSources; 28 | } 29 | 30 | public void setDataSources(Map dataSources) { 31 | this.dataSources = dataSources; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/exception/TransactionException.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.exception; 2 | 3 | import com.cheese.db.core.exception.DevBaseException; 4 | 5 | /** 6 | * devbase事务异常 7 | * 8 | * @author sobann 9 | */ 10 | public class TransactionException extends DevBaseException { 11 | 12 | public TransactionException(Exception e) { 13 | super(e.getMessage()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/DevBaseSqlInjector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector; 2 | 3 | 4 | import com.cheese.db.spring.wrappers.DevBaseSqlSessions; 5 | 6 | /** 7 | * sql注册器顶层接口 8 | * 9 | * @author sobann 10 | */ 11 | public interface DevBaseSqlInjector { 12 | 13 | void inspectInject(DevBaseSqlSessions devBaseSqlSessions, Class type) throws Exception; 14 | } 15 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/DevBaseSqlInjectorProvider.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector; 2 | 3 | /** 4 | * DevBaseSqlInjector 提供者顶层接口 5 | * sql注入提供者,根据sql注入的方式分别实现 6 | * 1.单体项目 基于事件的形式进行注册(使用spring广播器进行注册和监听) 7 | * 2.微服务架构 两种解决思路, 8 | * 2.1 专门使用某一个服务进行注册:其他服务只需要调用此服务(微服务调用),通过节点增加负载,注册信息改变时集群不受影响(只要注册节点重新注册即可) 9 | * 2.2 每一个服务都需要注册:需要定义一个注册服务用来管理集群上最新的注册信息,集群以及节点之间信息的同步使用rpc或dubbo的形式完成 10 | * 11 | * 12 | * @author sobann 13 | */ 14 | public interface DevBaseSqlInjectorProvider { 15 | 16 | DevBaseSqlInjector getDevBaseSqlInjector(); 17 | } 18 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/DevBaseStatementFactory.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector; 2 | 3 | import com.cheese.db.core.DevBaseConfiguration; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.injector.metadata.InjectMeta; 6 | import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; 7 | import org.apache.ibatis.executor.keygen.KeyGenerator; 8 | import org.apache.ibatis.executor.keygen.NoKeyGenerator; 9 | import org.apache.ibatis.mapping.MappedStatement; 10 | import org.apache.ibatis.mapping.ResultMap; 11 | import org.apache.ibatis.mapping.SqlCommandType; 12 | import org.apache.ibatis.mapping.SqlSource; 13 | import org.apache.ibatis.scripting.LanguageDriver; 14 | import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; 15 | import org.apache.ibatis.session.Configuration; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Map; 19 | 20 | /** 21 | * Statement构建工厂类 22 | * 23 | * @author sobann 24 | */ 25 | public class DevBaseStatementFactory implements DevBaseConstant { 26 | 27 | public static MappedStatement build(Configuration configuration, InjectMeta injectMeta, Class type) { 28 | LanguageDriver languageDriver = new XMLLanguageDriver(); 29 | String scriptContent = String.format(SCRIPT_TAG_TEMPLATE, injectMeta.getContent()); 30 | SqlSource sqlSource = languageDriver.createSqlSource(configuration, scriptContent, Map.class); 31 | String statementId = String.format(MAPPED_STATEMENT_ID_TEMPLATE, type.getName(), injectMeta.getCode()); 32 | KeyGenerator keyGenerator = new NoKeyGenerator(); 33 | String keyProperty = BLANK_STR; 34 | String keyColumn = BLANK_STR; 35 | if (SqlCommandType.INSERT == injectMeta.getSqlCommandType() && ((DevBaseConfiguration)configuration).getKeyGenerator().equals(Jdbc3KeyGenerator.class)) { 36 | keyGenerator = new Jdbc3KeyGenerator(); 37 | keyColumn = injectMeta.getKeyColumn(); 38 | keyProperty = ((DevBaseConfiguration)configuration).getInsertKeyProperty(); 39 | } 40 | MappedStatement ms = (new MappedStatement.Builder(configuration, statementId, sqlSource, injectMeta.getSqlCommandType())).keyGenerator(keyGenerator).keyProperty(keyProperty).keyColumn(keyColumn).resultMaps(new ArrayList() { 41 | { 42 | this.add((new org.apache.ibatis.mapping.ResultMap.Builder(configuration, "defaultResultMap", 43 | injectMeta.getReturnType(), 44 | new ArrayList<>(ZERO))).build()); 45 | } 46 | }).build(); 47 | return ms; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/InjectMetaCollector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector; 2 | 3 | import com.cheese.db.spring.injector.metadata.InjectMeta; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * injectMeta收集者 9 | * 10 | * @author sobann 11 | */ 12 | public interface InjectMetaCollector { 13 | 14 | /** 15 | * 收集注入sql的元数据 16 | * 17 | * @return 18 | */ 19 | List getInjectMetas(); 20 | } 21 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/SysSqlConfigInjectMetaCollector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector; 2 | 3 | import com.cheese.db.core.condition.Actions; 4 | import com.cheese.db.core.condition.load.LoadAction; 5 | import com.cheese.db.core.exception.StatementNotFoundException; 6 | import com.cheese.db.core.mapper.DB; 7 | import com.cheese.db.core.support.DevBaseConstant; 8 | import com.cheese.db.spring.injector.metadata.InjectMeta; 9 | import com.cheese.db.spring.support.DevBaseApplicationContextSupport; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | import java.util.Objects; 14 | 15 | /** 16 | * devbase系统配置库的sql收集 17 | * 18 | * @author sobann 19 | */ 20 | public class SysSqlConfigInjectMetaCollector extends DevBaseApplicationContextSupport implements InjectMetaCollector { 21 | 22 | private DB db; 23 | 24 | @Override 25 | public List getInjectMetas() { 26 | if (db == null) { 27 | db = DevBaseApplicationContextSupport.getBean(DB.class); 28 | } 29 | try { 30 | // 注册行为可以监听ContextRefreshedEvent事件 31 | LoadAction action = Actions.getLoad(DevBaseConstant.DEFAULT_SQL_CONFIG_DATASOURCE, DevBaseConstant.DEFAULT_SQL_CONFIG_CODE); 32 | List injectMetas = db.doActionGetList(action, InjectMeta.class); 33 | if (Objects.isNull(injectMetas)) { 34 | return Collections.emptyList(); 35 | } 36 | return injectMetas; 37 | }catch (StatementNotFoundException | NullPointerException e) { 38 | return Collections.emptyList(); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/TableInjectMetaCollector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector; 2 | 3 | import com.cheese.db.core.props.DataSourceConfig; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.datasource.DatasourceContext; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.support.DatasourceContextSupport; 8 | import com.cheese.db.spring.support.DevBaseApplicationContextSupport; 9 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 10 | import org.springframework.context.EnvironmentAware; 11 | import org.springframework.core.env.Environment; 12 | 13 | import java.util.*; 14 | 15 | /** 16 | * 抽象的表格元数据收集者 17 | * 18 | * @author sobann 19 | */ 20 | public abstract class TableInjectMetaCollector extends DevBaseApplicationContextSupport implements InjectMetaCollector, EnvironmentAware, DevBaseConstant { 21 | 22 | private boolean needLoad; 23 | private final List injectSchemas = new ArrayList<>(); 24 | 25 | @Override 26 | public List getInjectMetas() { 27 | DatasourceContext context = DatasourceContextSupport.support(); 28 | if (!needLoad || Objects.isNull(context) || Objects.isNull(context.getDataSources()) || context.getDataSources().isEmpty()) { 29 | return Collections.emptyList(); 30 | } 31 | Collection dataSourceConfigs = context.getDataSources().values(); 32 | for (DataSourceConfig dataSourceConfig : dataSourceConfigs) { 33 | DevBaseTableMetaSupport.bindDBSchema(dataSourceConfig.getSchemeName(), dataSourceConfig.getSchemeKey()); 34 | injectSchemas.add(dataSourceConfig.getSchemeName()); 35 | } 36 | List injectMetas = new ArrayList<>(); 37 | for (String injectSchema : injectSchemas) { 38 | final List tableMetas = this.getInjectMetas(injectSchema); 39 | injectMetas.addAll(tableMetas); 40 | } 41 | DatasourceContextSupport.clear(); 42 | return injectMetas; 43 | } 44 | 45 | @Override 46 | public void setEnvironment(Environment environment) { 47 | // 不启用时 48 | this.needLoad = environment.getProperty("devbase-db.use-default-config", Boolean.class, Boolean.FALSE); 49 | } 50 | 51 | /** 52 | * 根据数据库名称获取需要注入的表格元数据 53 | * 54 | * @param schema 55 | * @return 56 | */ 57 | protected abstract List getInjectMetas(String schema); 58 | 59 | } 60 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/dialect/DialectType.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.dialect; 2 | 3 | /** 4 | * 语义类型 5 | * 6 | * @author sobann 7 | */ 8 | public enum DialectType { 9 | /** 10 | * mysql 11 | */ 12 | Mysql, 13 | /** 14 | * oracle 15 | */ 16 | Oracle, 17 | /** 18 | * pg 19 | */ 20 | Postgres, 21 | /** 22 | * 23 | */ 24 | Sqlserver 25 | } 26 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/dialect/MysqlDialectCollector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.dialect; 2 | 3 | import com.cheese.db.core.condition.Actions; 4 | import com.cheese.db.core.condition.load.LoadAction; 5 | import com.cheese.db.core.mapper.DB; 6 | import com.cheese.db.core.support.DevBaseConstant; 7 | import com.cheese.db.spring.injector.collector.TableInjectMetaCollector; 8 | import com.cheese.db.spring.injector.collector.method.*; 9 | import com.cheese.db.spring.injector.metadata.InjectMeta; 10 | import com.cheese.db.spring.injector.metadata.TableMeta; 11 | import com.cheese.db.spring.injector.metadata.simple.MysqlTableMeta; 12 | import com.cheese.db.spring.support.DevBaseApplicationContextSupport; 13 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 14 | 15 | import java.util.*; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * mysql元数据提取 20 | * 21 | * @author sobann 22 | */ 23 | public class MysqlDialectCollector extends TableInjectMetaCollector { 24 | 25 | private List injectMethods; 26 | 27 | private DB db; 28 | 29 | public MysqlDialectCollector() { 30 | this.injectMethods = new ArrayList<>(); 31 | injectMethods.add(new Insert()); 32 | injectMethods.add(new Delete()); 33 | injectMethods.add(new Select()); 34 | injectMethods.add(new Update()); 35 | } 36 | 37 | public void addInjectMethods(AbstractMethod... methods) { 38 | if (Objects.isNull(injectMethods)) { 39 | this.injectMethods = new ArrayList<>(); 40 | } 41 | this.injectMethods.addAll(Arrays.asList(methods)); 42 | } 43 | 44 | public List getInjectMethods() { 45 | return injectMethods; 46 | } 47 | 48 | @Override 49 | protected List getInjectMetas(String schema) { 50 | if (db == null) { 51 | db = DevBaseApplicationContextSupport.getBean(DB.class); 52 | } 53 | LoadAction action = Actions.getLoad(DevBaseConstant.DEFAULT_SQL_CONFIG_DATASOURCE, DevBaseConstant.DEFAULT_TABLE_META_CONFIG_CODE); 54 | action.putParam(DevBaseConstant.TABLE_SCHEMA_KEY, schema); 55 | List tableMetaList = db.doActionGetList(action, MysqlTableMeta.class); 56 | if (Objects.isNull(tableMetaList) || tableMetaList.size() <= DevBaseConstant.ZERO) { 57 | return Collections.emptyList(); 58 | } 59 | List totalInjectMetas = new ArrayList<>(); 60 | // 按照表名分组 61 | Map> tableMetaListMap = tableMetaList.stream().collect(Collectors.groupingBy(MysqlTableMeta::getTableName)); 62 | for (String tableName : tableMetaListMap.keySet()) { 63 | final List oneTableMetaList = tableMetaListMap.get(tableName); 64 | TableMeta tablePrimary = findPrimaryTableMeta(schema, tableName, oneTableMetaList); 65 | if (Objects.isNull(tablePrimary)) continue; 66 | for (AbstractMethod injectMethod : getInjectMethods()) { 67 | InjectMeta injectMeta = injectMethod.buildInjectMeta(DialectType.Mysql, schema, tableName, tablePrimary, oneTableMetaList); 68 | if (Objects.isNull(injectMeta)) continue; 69 | totalInjectMetas.add(injectMeta); 70 | } 71 | } 72 | return totalInjectMetas; 73 | } 74 | 75 | 76 | /** 77 | * 获取表格元数据中的主键 78 | * 79 | * @param tableMetas 80 | * @return 81 | */ 82 | protected TableMeta findPrimaryTableMeta(String schema, String tableName, List tableMetas) { 83 | TableMeta primaryMeta = DevBaseTableMetaSupport.obtain(schema, tableName); 84 | if (Objects.nonNull(primaryMeta)) { 85 | return primaryMeta; 86 | } 87 | 88 | final MysqlTableMeta tablePrimary = tableMetas.stream().filter(item -> Objects.equals("PRI", item.getColumnKey())).findFirst().orElse(null); 89 | if (Objects.isNull(tablePrimary)) { 90 | return null; 91 | } 92 | DevBaseTableMetaSupport.bind(schema, tableName, tablePrimary); 93 | return tablePrimary; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/AbstractMethod.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | import com.cheese.db.spring.injector.collector.dialect.DialectType; 4 | import com.cheese.db.spring.injector.metadata.InjectMeta; 5 | import com.cheese.db.spring.injector.metadata.TableMeta; 6 | import com.cheese.db.spring.utils.SqlScriptUtils; 7 | 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * 抽象的注入方法 13 | * 14 | * @author sobann 15 | */ 16 | public abstract class AbstractMethod { 17 | 18 | /** 19 | * 构建通用的字段条件 20 | * 21 | * @param tableMetaList 22 | * @return 23 | */ 24 | protected String makeColumnParamScript(List tableMetaList) { 25 | return tableMetaList.stream() 26 | .map(TableMeta::getColumnName) 27 | .map(item -> SqlScriptUtils.convertIf(String.format("AND %s=#{ew.param.%s}", item, item), String.format("ew.param.%s != null", item), false)) 28 | .collect(Collectors.joining("\n")); 29 | } 30 | 31 | /** 32 | * 构建注入的sql元数据 33 | * 34 | * @param dialectType 35 | * @param schema 36 | * @param tableName 37 | * @param tablePrimary 38 | * @param oneTableMetaList 39 | * @return 40 | */ 41 | public abstract InjectMeta buildInjectMeta(DialectType dialectType, String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/Delete.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | import com.cheese.db.core.enums.ActionType; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.injector.collector.dialect.DialectType; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.injector.metadata.TableMeta; 8 | import com.cheese.db.spring.injector.metadata.simple.DefaultInjectMeta; 9 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 10 | import com.cheese.db.spring.utils.SqlScriptUtils; 11 | import org.apache.ibatis.mapping.SqlCommandType; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * 删除 17 | * 18 | * @author sobann 19 | */ 20 | public class Delete extends AbstractMethod { 21 | 22 | @Override 23 | public InjectMeta buildInjectMeta(DialectType dialectType, String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 24 | switch (dialectType) { 25 | case Mysql: 26 | return this.buildMysqlInjectMeta(schema, tableName, tablePrimary, oneTableMetaList); 27 | // todo 28 | case Oracle: 29 | case Postgres: 30 | case Sqlserver: 31 | default: 32 | return null; 33 | } 34 | } 35 | 36 | 37 | protected InjectMeta buildMysqlInjectMeta(String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 38 | if (tablePrimary == null) { 39 | return null; 40 | } 41 | final String dbKey = DevBaseTableMetaSupport.getDbKey(schema); 42 | // mysql中主键key字段columnKey值为PRI 43 | DefaultInjectMeta injectMeta = new DefaultInjectMeta(); 44 | injectMeta.setCode(dbKey + DevBaseConstant.TOKEN_SEPARATOR + tableName + DevBaseConstant.TOKEN_SEPARATOR + ActionType.DELETE.name()); 45 | injectMeta.setSqlCommandType(SqlCommandType.DELETE); 46 | injectMeta.setDbKey(dbKey); 47 | String columnScript = this.makeColumnParamScript(oneTableMetaList); 48 | String segmentScript = SqlScriptUtils.convertIf("${ew.sqlSegment}", "ew.sqlSegment != null", false); 49 | String columnWhereScript = SqlScriptUtils.convertWhere(columnScript + "\n" + segmentScript); 50 | String content = String.format(SqlMethod.DELETE.getSql(), tableName, columnWhereScript); 51 | injectMeta.setContent(content); 52 | return injectMeta; 53 | } 54 | } -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/Insert.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | import com.cheese.db.core.enums.ActionType; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.injector.collector.dialect.DialectType; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.injector.metadata.TableMeta; 8 | import com.cheese.db.spring.injector.metadata.simple.DefaultInjectMeta; 9 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 10 | import com.cheese.db.spring.utils.SqlScriptUtils; 11 | import org.apache.ibatis.mapping.SqlCommandType; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * 新增 18 | * 19 | * @author sobann 20 | */ 21 | public class Insert extends AbstractMethod { 22 | 23 | @Override 24 | public InjectMeta buildInjectMeta(DialectType dialectType, String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 25 | switch (dialectType) { 26 | case Mysql: 27 | return this.buildMysqlInjectMeta(schema, tableName, tablePrimary, oneTableMetaList); 28 | // todo 29 | case Oracle: 30 | case Postgres: 31 | case Sqlserver: 32 | default: 33 | return null; 34 | } 35 | } 36 | 37 | protected InjectMeta buildMysqlInjectMeta(String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 38 | if (tablePrimary == null) { 39 | return null; 40 | } 41 | final String dbKey = DevBaseTableMetaSupport.getDbKey(schema); 42 | // mysql中主键key字段columnKey值为PRI 43 | DefaultInjectMeta injectMeta = new DefaultInjectMeta(); 44 | injectMeta.setCode(dbKey + DevBaseConstant.TOKEN_SEPARATOR + tableName + DevBaseConstant.TOKEN_SEPARATOR + ActionType.INSERT.name()); 45 | injectMeta.setSqlCommandType(SqlCommandType.INSERT); 46 | injectMeta.setKeyColumn(tablePrimary.getColumnName()); 47 | injectMeta.setDbKey(dbKey); 48 | String columnScript = oneTableMetaList.stream().map(TableMeta::getColumnName).map(item -> SqlScriptUtils.convertIf(item + ",", String.format("ew.data.%s != null", item), false)).collect(Collectors.joining("\n")); 49 | String columnTrimScript = SqlScriptUtils.convertTrim(columnScript, "(", ")", null, ","); 50 | String valueScript = oneTableMetaList.stream().map(TableMeta::getColumnName).map(item -> SqlScriptUtils.convertIf(String.format("#{ew.data.%s},", item), String.format("ew.data.%s != null", item), false)).collect(Collectors.joining("\n")); 51 | String valueTrimScript = SqlScriptUtils.convertTrim(valueScript, "(", ")", null, ","); 52 | 53 | String content = String.format(SqlMethod.INSERT.getSql(), tableName, columnTrimScript, valueTrimScript); 54 | injectMeta.setContent(content); 55 | return injectMeta; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/Select.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | import com.cheese.db.core.enums.ActionType; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.injector.collector.dialect.DialectType; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.injector.metadata.TableMeta; 8 | import com.cheese.db.spring.injector.metadata.simple.DefaultInjectMeta; 9 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 10 | import com.cheese.db.spring.utils.SqlScriptUtils; 11 | import org.apache.ibatis.mapping.SqlCommandType; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * 查询 17 | * 18 | * @author sobann 19 | */ 20 | public class Select extends AbstractMethod{ 21 | 22 | @Override 23 | public InjectMeta buildInjectMeta(DialectType dialectType, String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 24 | switch (dialectType) { 25 | case Mysql: 26 | return this.buildMysqlInjectMeta(schema, tableName, tablePrimary, oneTableMetaList); 27 | // todo 28 | case Oracle: 29 | case Postgres: 30 | case Sqlserver: 31 | default: 32 | return null; 33 | } 34 | } 35 | 36 | protected InjectMeta buildMysqlInjectMeta(String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 37 | if (tablePrimary == null) { 38 | return null; 39 | } 40 | final String dbKey = DevBaseTableMetaSupport.getDbKey(schema); 41 | // mysql中主键key字段columnKey值为PRI 42 | DefaultInjectMeta injectMeta = new DefaultInjectMeta(); 43 | injectMeta.setCode(dbKey + DevBaseConstant.TOKEN_SEPARATOR + tableName + DevBaseConstant.TOKEN_SEPARATOR + ActionType.SELECT.name()); 44 | injectMeta.setSqlCommandType(SqlCommandType.SELECT); 45 | injectMeta.setDbKey(dbKey); 46 | String selectScript = SqlScriptUtils.convertChoose(String.format("%s != null and %s != null", "ew", "ew.sqlSelect"), SqlScriptUtils.unSafeParam("ew.sqlSelect"), DevBaseConstant.SQL_ALL); 47 | String columnScript = this.makeColumnParamScript(oneTableMetaList); 48 | String segmentScript = SqlScriptUtils.convertIf("${ew.sqlSegment}", "ew.sqlSegment != null", false); 49 | String columnWhereScript = SqlScriptUtils.convertWhere(columnScript + "\n" + segmentScript); 50 | String content = String.format(SqlMethod.SELECT.getSql(), selectScript, tableName, columnWhereScript); 51 | injectMeta.setContent(content); 52 | return injectMeta; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/SqlMethod.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | /** 4 | * 参考mybatis-plus 5 | * 6 | * @author sobann 7 | */ 8 | public enum SqlMethod { 9 | 10 | /** 11 | * 新增 12 | */ 13 | INSERT("insert", "插入一条数据(选择字段插入)", "INSERT INTO %s %s VALUES %s"), 14 | 15 | /** 16 | * 删除 17 | */ 18 | DELETE("delete", "根据 entity 条件删除记录", "DELETE FROM %s %s"), 19 | 20 | /** 21 | * 修改 22 | */ 23 | UPDATE("update", "根据条件,更新记录", "UPDATE %s %s %s"), 24 | 25 | /** 26 | * 查询 27 | */ 28 | SELECT("selectList", "查询满足条件所有数据", "SELECT %s FROM %s %s"); 29 | 30 | 31 | private final String method; 32 | private final String desc; 33 | private final String sql; 34 | 35 | SqlMethod(String method, String desc, String sql) { 36 | this.method = method; 37 | this.desc = desc; 38 | this.sql = sql; 39 | } 40 | 41 | public String getMethod() { 42 | return method; 43 | } 44 | 45 | public String getDesc() { 46 | return desc; 47 | } 48 | 49 | public String getSql() { 50 | return sql; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/collector/method/Update.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.collector.method; 2 | 3 | import com.cheese.db.core.enums.ActionType; 4 | import com.cheese.db.core.support.DevBaseConstant; 5 | import com.cheese.db.spring.injector.collector.dialect.DialectType; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.injector.metadata.TableMeta; 8 | import com.cheese.db.spring.injector.metadata.simple.DefaultInjectMeta; 9 | import com.cheese.db.spring.support.DevBaseTableMetaSupport; 10 | import com.cheese.db.spring.utils.SqlScriptUtils; 11 | import org.apache.ibatis.mapping.SqlCommandType; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * 修改 18 | * 19 | * @author sobann 20 | */ 21 | public class Update extends AbstractMethod { 22 | 23 | @Override 24 | public InjectMeta buildInjectMeta(DialectType dialectType, String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 25 | switch (dialectType) { 26 | case Mysql: 27 | return this.buildMysqlInjectMeta(schema, tableName, tablePrimary, oneTableMetaList); 28 | // todo 29 | case Oracle: 30 | case Postgres: 31 | case Sqlserver: 32 | default: 33 | return null; 34 | } 35 | } 36 | 37 | protected InjectMeta buildMysqlInjectMeta(String schema, String tableName, TableMeta tablePrimary, List oneTableMetaList) { 38 | if (tablePrimary == null) { 39 | return null; 40 | } 41 | final String dbKey = DevBaseTableMetaSupport.getDbKey(schema); 42 | // mysql中主键key字段columnKey值为PRI 43 | DefaultInjectMeta injectMeta = new DefaultInjectMeta(); 44 | injectMeta.setCode(dbKey + DevBaseConstant.TOKEN_SEPARATOR + tableName + DevBaseConstant.TOKEN_SEPARATOR + ActionType.UPDATE.name()); 45 | injectMeta.setSqlCommandType(SqlCommandType.UPDATE); 46 | injectMeta.setDbKey(dbKey); 47 | String setColumnScript = oneTableMetaList.stream().map(TableMeta::getColumnName).map(item -> SqlScriptUtils.convertIf(String.format("%s=#{ew.data.%s},", item, item), String.format("ew.data.%s != null", item), false)) .collect(Collectors.joining("\n")); 48 | String whereColumnScript = this.makeColumnParamScript(oneTableMetaList); 49 | String segmentScript = SqlScriptUtils.convertIf("${ew.sqlSegment}", "ew.sqlSegment != null", false); 50 | String columnWhereScript = SqlScriptUtils.convertWhere(whereColumnScript + "\n" + segmentScript); 51 | String columnSetScript = SqlScriptUtils.convertSet(setColumnScript); 52 | String content = String.format(SqlMethod.UPDATE.getSql(), tableName, columnSetScript, columnWhereScript); 53 | injectMeta.setContent(content); 54 | return injectMeta; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/event/DevBaseSqlInjectListener.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.event; 2 | 3 | import com.cheese.db.core.mapper.DB; 4 | import com.cheese.db.spring.injector.collector.InjectMetaCollector; 5 | import com.cheese.db.spring.injector.event.runtime.DefaultEventSqlInjector; 6 | import com.cheese.db.spring.injector.metadata.InjectMeta; 7 | import com.cheese.db.spring.support.DevBaseApplicationContextSupport; 8 | import com.cheese.db.spring.wrappers.DevBaseSqlSessions; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.context.ApplicationEvent; 12 | import org.springframework.context.event.ContextRefreshedEvent; 13 | import org.springframework.context.event.SmartApplicationListener; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * sql注入监听器 21 | * 22 | * @author sobann 23 | */ 24 | public class DevBaseSqlInjectListener extends DevBaseApplicationContextSupport implements SmartApplicationListener { 25 | 26 | private static Logger logger = LoggerFactory.getLogger(DevBaseSqlInjectListener.class); 27 | private DevBaseSqlSessions sqlSessions; 28 | 29 | 30 | @Override 31 | public boolean supportsEventType(Class eventType) { 32 | return eventType.isAssignableFrom(ContextRefreshedEvent.class) || eventType.isAssignableFrom(SqlInjectEvent.class); 33 | } 34 | 35 | 36 | @Override 37 | public void onApplicationEvent(ApplicationEvent event) { 38 | if (event instanceof ContextRefreshedEvent) { 39 | onApplicationContextRefreshedEvent((ContextRefreshedEvent) event); 40 | } 41 | 42 | if (event instanceof SqlInjectEvent) { 43 | onApplicationSqlInjectEvent((SqlInjectEvent) event); 44 | } 45 | 46 | 47 | } 48 | 49 | /** 50 | * 容器刷新事件 51 | * 52 | * @param event 53 | */ 54 | private void onApplicationContextRefreshedEvent(ContextRefreshedEvent event) { 55 | List injectMetaList = new ArrayList<>(); 56 | final Map injectMetaCollectors = DevBaseApplicationContextSupport.getBeans(InjectMetaCollector.class); 57 | for (InjectMetaCollector collector : injectMetaCollectors.values()) { 58 | final List injectMetas = collector.getInjectMetas(); 59 | injectMetaList.addAll(injectMetas); 60 | } 61 | //默认注入到DB.class中,可根据项目实际持久层mapper实现 62 | DevBaseApplicationContextSupport.getApplicationContext().publishEvent(new SqlInjectEvent(this, DB.class, InjectType.ALL, injectMetaList)); 63 | } 64 | 65 | 66 | /** 67 | * sql注入事件 68 | * 69 | * @param event 70 | */ 71 | private void onApplicationSqlInjectEvent(SqlInjectEvent event) { 72 | if (sqlSessions == null) { 73 | sqlSessions = DevBaseApplicationContextSupport.getBean(DevBaseSqlSessions.class); 74 | } 75 | logger.info("the sqlInjectEvent was monitored, ready to start sql injection"); 76 | try { 77 | Class mapperInterface = event.getMapperInterface(); 78 | DefaultEventSqlInjector eventSqlInjector = new DefaultEventSqlInjector.Builder(event.getInjectType(), 79 | event.getInjectMetaList()).build(); 80 | eventSqlInjector.inspectInject(sqlSessions, mapperInterface); 81 | logger.info("the sqlInjectEvent was completed"); 82 | } catch (Exception e) { 83 | logger.error("the sqlInjectEvent was failed, the reason is {}", e.getMessage()); 84 | e.printStackTrace(); 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/event/InjectType.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.event; 2 | 3 | /** 4 | * sql注册行为 5 | * 1.ALL注册所有 6 | * 2.SINGLE单个sql注册 7 | * 3.REFRESH重置 8 | * 9 | * @author sobann 10 | */ 11 | public enum InjectType { 12 | ALL, SINGLE, REFRESH 13 | } 14 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/event/SqlInjectEvent.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.event; 2 | 3 | import com.cheese.db.spring.injector.metadata.InjectMeta; 4 | import org.springframework.context.ApplicationEvent; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * sql注入事件 10 | * 11 | * @author sobann 12 | */ 13 | public class SqlInjectEvent extends ApplicationEvent { 14 | 15 | private final Class mapperInterface; 16 | 17 | private final InjectType injectType; 18 | 19 | private final List injectMetaList; 20 | 21 | /** 22 | * Create a new ApplicationEvent. 23 | * 24 | * @param source the object on which the event initially occurred (never {@code null}) 25 | */ 26 | public SqlInjectEvent(Object source,Class mapperInterface, InjectType injectType, List injectMetaList) { 27 | super(source); 28 | this.mapperInterface = mapperInterface; 29 | this.injectType = injectType; 30 | this.injectMetaList = injectMetaList; 31 | } 32 | 33 | public Class getMapperInterface() { 34 | return mapperInterface; 35 | } 36 | 37 | public InjectType getInjectType() { 38 | return injectType; 39 | } 40 | 41 | public List getInjectMetaList() { 42 | return injectMetaList; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/event/runtime/DefaultEventSqlInjector.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.event.runtime; 2 | 3 | import com.cheese.db.core.DevBaseConfiguration; 4 | import com.cheese.db.spring.injector.DevBaseSqlInjector; 5 | import com.cheese.db.spring.injector.DevBaseStatementFactory; 6 | import com.cheese.db.spring.injector.event.InjectType; 7 | import com.cheese.db.spring.injector.metadata.InjectMeta; 8 | import com.cheese.db.spring.wrappers.DevBaseSqlSessions; 9 | import org.apache.ibatis.mapping.MappedStatement; 10 | import org.apache.ibatis.session.SqlSession; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.util.CollectionUtils; 14 | 15 | import java.util.*; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * 默认的基于事件的sql注册器 20 | * 运行时进行注册,基于发布SqlInjectEvent事件 21 | * 22 | * @author sobann 23 | */ 24 | public class DefaultEventSqlInjector implements DevBaseSqlInjector { 25 | private static Logger logger = LoggerFactory.getLogger(DefaultEventSqlInjector.class); 26 | private final InjectType injectType; 27 | private final Map> injectMetaList; 28 | 29 | public DefaultEventSqlInjector(InjectType injectType, Map> injectMetaList) { 30 | this.injectType = injectType; 31 | this.injectMetaList = injectMetaList; 32 | } 33 | 34 | @Override 35 | public void inspectInject(DevBaseSqlSessions devBaseSqlSessions, Class type) throws Exception { 36 | Map sqlSessions = devBaseSqlSessions.getSqlSessions(); 37 | for (Map.Entry entry : sqlSessions.entrySet()) { 38 | //匹配项 根据数据源分组 39 | String dbKey = entry.getKey(); 40 | List injectMetas = injectMetaList.get(dbKey); 41 | if (CollectionUtils.isEmpty(injectMetas)) continue; 42 | SqlSession sqlSession = entry.getValue(); 43 | //获取到自己的配置类 44 | DevBaseConfiguration configuration = (DevBaseConfiguration) sqlSession.getConfiguration(); 45 | for (InjectMeta injectMeta : injectMetas) { 46 | MappedStatement mappedStatement = DevBaseStatementFactory.build(configuration, injectMeta, type); 47 | configuration.addMappedStatement(mappedStatement); 48 | logger.debug("mappedStatement has registered, which code is {} ", mappedStatement.getId()); 49 | } 50 | } 51 | } 52 | 53 | 54 | public static class Builder { 55 | 56 | private InjectType injectType; 57 | private List injectMetaList; 58 | 59 | public Builder(InjectType injectType, List injectMetaList) { 60 | this.injectType = injectType; 61 | this.injectMetaList = injectMetaList; 62 | } 63 | 64 | public DefaultEventSqlInjector build() { 65 | this.injectType = Optional.ofNullable(this.injectType).orElse(InjectType.ALL); 66 | this.injectMetaList = Optional.ofNullable(this.injectMetaList).orElse(Collections.emptyList()); 67 | Map> injectMetaListGrop = injectMetaList.stream().filter(item -> Objects.nonNull(item.getDbKey())).collect(Collectors.groupingBy(InjectMeta::getDbKey)); 68 | return new DefaultEventSqlInjector(injectType, injectMetaListGrop); 69 | } 70 | 71 | 72 | public InjectType getInjectType() { 73 | return injectType; 74 | } 75 | 76 | public void setInjectType(InjectType injectType) { 77 | this.injectType = injectType; 78 | } 79 | 80 | public List getInjectMetaList() { 81 | return injectMetaList; 82 | } 83 | 84 | public void setInjectMetaList(List injectMetaList) { 85 | this.injectMetaList = injectMetaList; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/metadata/InjectMeta.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.metadata; 2 | 3 | import com.cheese.db.core.support.DevBaseConstant; 4 | import org.apache.ibatis.mapping.SqlCommandType; 5 | 6 | /** 7 | * sql元数据 顶层接口 8 | * 9 | * @author sobann 10 | */ 11 | public interface InjectMeta extends DevBaseConstant { 12 | 13 | String getDbKey(); 14 | 15 | void setDbKey(String dbKey); 16 | 17 | String getContent(); 18 | 19 | void setContent(String content); 20 | 21 | String getCode(); 22 | 23 | void setCode(String code); 24 | 25 | SqlCommandType getSqlCommandType(); 26 | 27 | void setSqlCommandType(SqlCommandType sqlCommandType); 28 | 29 | Class getReturnType(); 30 | 31 | void setReturnType(Class returnType); 32 | 33 | Class getMapperInterface(); 34 | 35 | void setMapperInterface(Class mapperInterface); 36 | 37 | String getKeyColumn(); 38 | 39 | void setKeyColumn(String keyColumn); 40 | } 41 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/metadata/TableMeta.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.metadata; 2 | 3 | /** 4 | * 表格元数据 5 | * 6 | * @author sobann 7 | */ 8 | public interface TableMeta { 9 | 10 | /** 11 | * 数据库名称 12 | * 13 | * @return 14 | */ 15 | String getTableSchema(); 16 | 17 | /** 18 | * 数据表名称 19 | * 20 | * @return 21 | */ 22 | String getTableName(); 23 | 24 | /** 25 | * 数据字段名称 26 | * 27 | * @return 28 | */ 29 | String getColumnName(); 30 | 31 | /** 32 | * 索引类型 33 | * 34 | * @return 35 | */ 36 | String getColumnKey(); 37 | 38 | /** 39 | * 数据类型 40 | * 41 | * @return 42 | */ 43 | String getDataType(); 44 | } 45 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/metadata/simple/DefaultInjectMeta.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.metadata.simple; 2 | 3 | import com.cheese.db.spring.injector.metadata.InjectMeta; 4 | import org.apache.ibatis.mapping.SqlCommandType; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * 默认的sql元数据 10 | * 11 | * @author sobann 12 | */ 13 | public class DefaultInjectMeta implements InjectMeta { 14 | 15 | private String dbKey; 16 | 17 | private String content; 18 | 19 | private String code; 20 | 21 | private int sqlCommandTypeCode; 22 | 23 | private SqlCommandType sqlCommandType; 24 | 25 | private Class returnType; 26 | 27 | private Class mapperInterface; 28 | 29 | private String keyColumn; 30 | 31 | public int getSqlCommandTypeCode() { 32 | return sqlCommandTypeCode; 33 | } 34 | 35 | public void setSqlCommandTypeCode(int sqlCommandTypeCode) { 36 | this.sqlCommandTypeCode = sqlCommandTypeCode; 37 | switch (sqlCommandTypeCode){ 38 | case ZERO: 39 | this.sqlCommandType = SqlCommandType.SELECT; 40 | break; 41 | case ONE: 42 | this.sqlCommandType = SqlCommandType.INSERT; 43 | break; 44 | case TWO: 45 | this.sqlCommandType = SqlCommandType.UPDATE; 46 | break; 47 | case THREE: 48 | this.sqlCommandType = SqlCommandType.DELETE; 49 | break; 50 | } 51 | } 52 | 53 | @Override 54 | public String getDbKey() { 55 | return dbKey; 56 | } 57 | 58 | @Override 59 | public void setDbKey(String dbKey) { 60 | this.dbKey = dbKey; 61 | } 62 | 63 | @Override 64 | public String getContent() { 65 | return content; 66 | } 67 | 68 | @Override 69 | public void setContent(String content) { 70 | this.content = content; 71 | } 72 | 73 | @Override 74 | public String getCode() { 75 | return code; 76 | } 77 | 78 | @Override 79 | public void setCode(String code) { 80 | this.code = code; 81 | } 82 | 83 | @Override 84 | public SqlCommandType getSqlCommandType() { 85 | return sqlCommandType; 86 | } 87 | 88 | @Override 89 | public void setSqlCommandType(SqlCommandType sqlCommandType) { 90 | this.sqlCommandType = sqlCommandType; 91 | } 92 | 93 | @Override 94 | public Class getReturnType() { 95 | if (returnType == null) return Map.class; 96 | return returnType; 97 | } 98 | 99 | @Override 100 | public void setReturnType(Class returnType) { 101 | this.returnType = returnType; 102 | } 103 | 104 | @Override 105 | public Class getMapperInterface() { 106 | return mapperInterface; 107 | } 108 | 109 | @Override 110 | public void setMapperInterface(Class mapperInterface) { 111 | this.mapperInterface = mapperInterface; 112 | } 113 | 114 | @Override 115 | public String getKeyColumn() { 116 | return keyColumn; 117 | } 118 | 119 | @Override 120 | public void setKeyColumn(String keyProperty) { 121 | this.keyColumn = keyProperty; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/metadata/simple/MysqlTableMeta.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.metadata.simple; 2 | 3 | import com.cheese.db.spring.injector.metadata.TableMeta; 4 | 5 | /** 6 | * 默认的表格元数据收集 7 | * 8 | * @author sobann 9 | */ 10 | public class MysqlTableMeta implements TableMeta { 11 | 12 | private String tableSchema; 13 | 14 | private String tableName; 15 | 16 | private String columnName; 17 | 18 | private String columnKey; 19 | 20 | private String dataType; 21 | 22 | @Override 23 | public String getTableSchema() { 24 | return tableSchema; 25 | } 26 | 27 | public void setTableSchema(String tableSchema) { 28 | this.tableSchema = tableSchema; 29 | } 30 | 31 | @Override 32 | public String getTableName() { 33 | return tableName; 34 | } 35 | 36 | public void setTableName(String tableName) { 37 | this.tableName = tableName; 38 | } 39 | 40 | @Override 41 | public String getColumnName() { 42 | return columnName; 43 | } 44 | 45 | public void setColumnName(String columnName) { 46 | this.columnName = columnName; 47 | } 48 | 49 | @Override 50 | public String getColumnKey() { 51 | return columnKey; 52 | } 53 | 54 | public void setColumnKey(String columnKey) { 55 | this.columnKey = columnKey; 56 | } 57 | 58 | @Override 59 | public String getDataType() { 60 | return dataType; 61 | } 62 | 63 | public void setDataType(String dataType) { 64 | this.dataType = dataType; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/injector/simple/DefaultDevBaseSqlInjectorProvider.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.injector.simple; 2 | 3 | import com.cheese.db.core.support.DevBaseConstant; 4 | import com.cheese.db.spring.injector.DevBaseSqlInjector; 5 | import com.cheese.db.spring.injector.DevBaseSqlInjectorProvider; 6 | import com.cheese.db.spring.injector.DevBaseStatementFactory; 7 | import com.cheese.db.spring.injector.metadata.simple.DefaultInjectMeta; 8 | import com.cheese.db.spring.injector.metadata.simple.MysqlTableMeta; 9 | import org.apache.ibatis.mapping.MappedStatement; 10 | import org.apache.ibatis.mapping.SqlCommandType; 11 | import org.apache.ibatis.session.Configuration; 12 | import org.apache.ibatis.session.SqlSession; 13 | 14 | import java.util.Map; 15 | 16 | /** 17 | * 默认的sqlInjector提供者 18 | * 1.项目启动时 19 | * a.注册sys_config_sql等数据的查询功能 20 | * b.todo 基础增上改查扩展,增加表的增删改元数据配置表 (后续完成) 21 | * 22 | * @author sobann 23 | */ 24 | public class DefaultDevBaseSqlInjectorProvider implements DevBaseSqlInjectorProvider, DevBaseConstant { 25 | 26 | private static DefaultInjectMeta injectMeta = new DefaultInjectMeta(); 27 | private static DefaultInjectMeta tableMeta = new DefaultInjectMeta(); 28 | 29 | static { 30 | // 配置的sql 31 | injectMeta.setCode(DEFAULT_SQL_CONFIG_CODE); 32 | injectMeta.setSqlCommandType(SqlCommandType.SELECT); 33 | injectMeta.setReturnType(DefaultInjectMeta.class); 34 | injectMeta.setDbKey(DEFAULT_SQL_CONFIG_DATASOURCE); 35 | injectMeta.setContent(DEFAULT_MYSQL_SYS_CONFIG_SQL); 36 | 37 | // 表格元数据sql 38 | tableMeta.setCode(DEFAULT_TABLE_META_CONFIG_CODE); 39 | tableMeta.setSqlCommandType(SqlCommandType.SELECT); 40 | tableMeta.setReturnType(MysqlTableMeta.class); 41 | tableMeta.setDbKey(ALL_IDENTIFIER); 42 | tableMeta.setContent(DEFAULT_MYSQL_TABLE_META_CONFIG_SQL); 43 | } 44 | 45 | @Override 46 | public DevBaseSqlInjector getDevBaseSqlInjector() { 47 | //默认注册的sql目前仅有sys_config_sql的内容 48 | return (devBaseSqlSessions, type) -> { 49 | Map sqlSessions = devBaseSqlSessions.getSqlSessions(); 50 | for (Map.Entry entry : sqlSessions.entrySet()) { 51 | Configuration configuration = entry.getValue().getConfiguration(); 52 | MappedStatement tableMetaStatement = DevBaseStatementFactory.build(configuration, tableMeta, type); 53 | configuration.addMappedStatement(tableMetaStatement); 54 | if (!DEFAULT_SQL_CONFIG_DATASOURCE.equals(entry.getKey())) continue; 55 | MappedStatement extraSqlStatement = DevBaseStatementFactory.build(configuration, injectMeta, type); 56 | configuration.addMappedStatement(extraSqlStatement); 57 | } 58 | 59 | }; 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/mapper/DevBaseMapperFactoryBean.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.mapper; 2 | 3 | import com.cheese.db.core.condition.manager.DevBaseActionManager; 4 | import com.cheese.db.core.proxy.DevBaseMapperProxyFactory; 5 | import com.cheese.db.spring.injector.DevBaseSqlInjector; 6 | import com.cheese.db.spring.support.DevBaseMapperRegistrySupport; 7 | import com.cheese.db.spring.support.DevBaseSqlSessionDaoSupport; 8 | import org.apache.ibatis.session.SqlSession; 9 | import org.springframework.beans.factory.FactoryBean; 10 | import org.springframework.util.CollectionUtils; 11 | 12 | import java.util.Map; 13 | 14 | /** 15 | * mybatis与spring框架串联的核心 16 | * 1.完成持久层实例工厂的创建 17 | * 2.sqlInjector功能的接入点 18 | * 3.持久层代理实例的获取 19 | * 20 | * @author sobann 21 | */ 22 | public class DevBaseMapperFactoryBean extends DevBaseSqlSessionDaoSupport implements FactoryBean { 23 | 24 | //当前注册的工厂实例与Mybatis的不同,通过一个mapper代理多个数据源以及相关的方法 25 | private Class mapperInterface; 26 | 27 | private boolean addToConfig = true; 28 | 29 | public DevBaseMapperFactoryBean() { 30 | // intentionally empty 31 | } 32 | 33 | public DevBaseMapperFactoryBean(Class mapperInterface) { 34 | this.mapperInterface = mapperInterface; 35 | } 36 | 37 | @Override 38 | public T getObject() throws Exception { 39 | return (T) DevBaseMapperRegistrySupport.get(getObjectType()).newInstance(); 40 | } 41 | 42 | public void setMapperInterface(Class mapperInterface) { 43 | this.mapperInterface = mapperInterface; 44 | } 45 | 46 | @Override 47 | public Class getObjectType() { 48 | return mapperInterface; 49 | } 50 | 51 | @Override 52 | protected void checkDaoConfig() throws IllegalArgumentException { 53 | //mybatis框架原始:多个MapperProxyFactory使用同一个sqlSessionTemplate 54 | //DevBase需求:一个MapperProxyFactory代理多个sqlSessionTemplate,发起调用时选择 55 | super.checkDaoConfig(); 56 | try { 57 | if (!DevBaseMapperRegistrySupport.hasRegister(mapperInterface)) { 58 | Map sqlSessionTemplates = this.getDevBaseSqlSessionTemplates().getSqlSessions(); 59 | DevBaseActionManager devBaseActionManager = this.getDevBaseActionManager(); 60 | if (!CollectionUtils.isEmpty(sqlSessionTemplates)) { 61 | //创建代理对象 62 | DevBaseMapperProxyFactory proxyFactory = new DevBaseMapperProxyFactory<>(mapperInterface, sqlSessionTemplates, devBaseActionManager); 63 | DevBaseMapperRegistrySupport.put(mapperInterface, proxyFactory); 64 | //注入statement,需要根据数据库中sql的db选项注入到对应的Configuration中 65 | DevBaseSqlInjector devBaseSqlInjector = getDevBaseSqlInjector(); 66 | devBaseSqlInjector.inspectInject(getDevBaseSqlSessionTemplates(), mapperInterface); 67 | } 68 | DevBaseMapperRegistrySupport.completeRegister(mapperInterface, true); 69 | } 70 | } catch (Exception e) { 71 | DevBaseMapperRegistrySupport.completeRegister(mapperInterface, false); 72 | //todo 守护线程后置重新注册 73 | } 74 | } 75 | 76 | @Override 77 | public boolean isSingleton() { 78 | return true; 79 | } 80 | 81 | 82 | /** 83 | * Return the mapper interface of the MyBatis mapper 84 | * 85 | * @return class of the interface 86 | */ 87 | public Class getMapperInterface() { 88 | return mapperInterface; 89 | } 90 | 91 | public void setAddToConfig(boolean addToConfig) { 92 | this.addToConfig = addToConfig; 93 | } 94 | 95 | /** 96 | * Return the flag for addition into MyBatis config. 97 | * 98 | * @return true if the mapper will be added to MyBatis in the case it is not already registered. 99 | */ 100 | public boolean isAddToConfig() { 101 | return addToConfig; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/support/DatasourceContextSupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.support; 2 | 3 | import com.cheese.db.spring.datasource.DatasourceContext; 4 | 5 | /** 6 | * 上下文提供者 7 | * 8 | * @author sobann 9 | */ 10 | public class DatasourceContextSupport { 11 | 12 | private static ThreadLocal DATASOURCE_CONTEXT = ThreadLocal.withInitial(DatasourceContext::new); 13 | 14 | /** 15 | * 提供数据源上下文 16 | * 17 | * @return 18 | */ 19 | public static DatasourceContext support() { 20 | return DATASOURCE_CONTEXT.get(); 21 | } 22 | 23 | /** 24 | * 设置数据源上下文 25 | * 26 | * @param datasourceContext 27 | */ 28 | public static void set(DatasourceContext datasourceContext) { 29 | DATASOURCE_CONTEXT.set(datasourceContext); 30 | } 31 | 32 | /** 33 | * 清空当前线程的上下文数据 34 | */ 35 | public static void clear() { 36 | DATASOURCE_CONTEXT.remove(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/support/DevBaseApplicationContextSupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.support; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactoryUtils; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * spring 上下文感知 12 | * 13 | * @author sobann 14 | */ 15 | public abstract class DevBaseApplicationContextSupport implements ApplicationContextAware { 16 | 17 | private static ApplicationContext applicationContext; 18 | 19 | public static ApplicationContext getApplicationContext() { 20 | return applicationContext; 21 | } 22 | 23 | public static T getBean(Class clazz) { 24 | return (T) applicationContext.getBean(clazz); 25 | } 26 | 27 | public static Object getBean(String name) throws BeansException { 28 | return applicationContext.getBean(name); 29 | } 30 | 31 | public static Map getBeans(Class clazz) { 32 | return BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, clazz, true, false); 33 | } 34 | @Override 35 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 36 | if(DevBaseApplicationContextSupport.applicationContext == null) { 37 | DevBaseApplicationContextSupport.applicationContext = applicationContext; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/support/DevBaseMapperRegistrySupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.support; 2 | 3 | 4 | import com.cheese.db.core.proxy.DevBaseMapperProxyFactory; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * devbase与mybatis原始功能不同 11 | * action中的参数是控制的核心而不是方法入口!!! 12 | * 13 | * @author sobann 14 | */ 15 | public class DevBaseMapperRegistrySupport { 16 | 17 | private static Map, Boolean> MAPPER_REGISTER_STATUS = new ConcurrentHashMap<>(); 18 | private static Map, DevBaseMapperProxyFactory> PROXY_FACTORY_CACHE = new ConcurrentHashMap<>(); 19 | 20 | public static void put(Class mapperInterface, DevBaseMapperProxyFactory proxyFactory) { 21 | PROXY_FACTORY_CACHE.put(mapperInterface, proxyFactory); 22 | } 23 | 24 | public static DevBaseMapperProxyFactory get(Class mapperInterface) { 25 | DevBaseMapperProxyFactory proxyFactory = PROXY_FACTORY_CACHE.get(mapperInterface); 26 | return proxyFactory; 27 | } 28 | 29 | public static boolean hasRegister(Class mapperInterface) { 30 | return MAPPER_REGISTER_STATUS.getOrDefault(mapperInterface, false); 31 | } 32 | 33 | public static void completeRegister(Class mapperInterface, boolean mapperLoadStatus) { 34 | MAPPER_REGISTER_STATUS.put(mapperInterface, mapperLoadStatus); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/support/DevBaseSqlSessionDaoSupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.support; 2 | 3 | 4 | import com.cheese.db.core.condition.manager.DevBaseActionManager; 5 | import com.cheese.db.spring.injector.DevBaseSqlInjector; 6 | import com.cheese.db.spring.wrappers.DevBaseSqlSessions; 7 | import org.springframework.dao.support.DaoSupport; 8 | import org.springframework.util.Assert; 9 | 10 | /** 11 | * 多数据源相关属性提供者 12 | * 13 | * @author sobann 14 | */ 15 | public abstract class DevBaseSqlSessionDaoSupport extends DaoSupport { 16 | 17 | private DevBaseSqlSessions devBaseSqlSessionTemplates; 18 | private DevBaseActionManager devBaseActionManager; 19 | private DevBaseSqlInjector devBaseSqlInjector; 20 | 21 | public DevBaseSqlSessions getDevBaseSqlSessionTemplates() { 22 | return devBaseSqlSessionTemplates; 23 | } 24 | 25 | public void setDevBaseSqlSessionTemplates(DevBaseSqlSessions devBaseSqlSessionTemplates) { 26 | this.devBaseSqlSessionTemplates = devBaseSqlSessionTemplates; 27 | } 28 | 29 | public DevBaseActionManager getDevBaseActionManager() { 30 | return devBaseActionManager; 31 | } 32 | 33 | public void setDevBaseActionManager(DevBaseActionManager devBaseActionManager) { 34 | this.devBaseActionManager = devBaseActionManager; 35 | } 36 | 37 | public DevBaseSqlInjector getDevBaseSqlInjector() { 38 | return devBaseSqlInjector; 39 | } 40 | 41 | public void setDevBaseSqlInjector(DevBaseSqlInjector devBaseSqlInjector) { 42 | this.devBaseSqlInjector = devBaseSqlInjector; 43 | } 44 | 45 | @Override 46 | protected void checkDaoConfig() throws IllegalArgumentException { 47 | Assert.notNull(this.devBaseSqlSessionTemplates, "Property 'sqlSessionTemplates' are required"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/support/DevBaseTableMetaSupport.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.support; 2 | 3 | import com.cheese.db.core.support.DevBaseConstant; 4 | import com.cheese.db.spring.injector.metadata.TableMeta; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * 表格元数据处理缓存 11 | * 12 | * @author sobann 13 | */ 14 | public class DevBaseTableMetaSupport implements DevBaseConstant { 15 | 16 | private static Map DB_SCHEMA = new ConcurrentHashMap<>(); 17 | private static Map TABLE_PRIMARY = new ConcurrentHashMap<>(); 18 | 19 | public static void bindDBSchema(String schema, String dbKey) { 20 | DB_SCHEMA.put(schema, dbKey); 21 | } 22 | 23 | public static String getDbKey(String schema) { 24 | return DB_SCHEMA.get(schema); 25 | } 26 | 27 | public static void bind(String schema, String tableName, TableMeta primaryMeta) { 28 | TABLE_PRIMARY.put(schema + TOKEN_SEPARATOR + tableName, primaryMeta); 29 | } 30 | 31 | public static TableMeta obtain(String schema, String tableName) { 32 | return TABLE_PRIMARY.get(schema + TOKEN_SEPARATOR + tableName); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/transaction/aop/DevBaseAnnotationsTransactionMethodInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.transaction.aop; 2 | 3 | import cn.hutool.core.lang.Pair; 4 | import com.cheese.db.spring.annotation.DevBaseMultiDataSourceTransactional; 5 | import com.cheese.db.spring.exception.TransactionException; 6 | import com.cheese.db.spring.wrappers.DevBaseDataSourceTransactionManagers; 7 | import org.aopalliance.intercept.MethodInterceptor; 8 | import org.aopalliance.intercept.MethodInvocation; 9 | import org.springframework.core.annotation.AnnotationUtils; 10 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 | import org.springframework.transaction.TransactionDefinition; 12 | import org.springframework.transaction.TransactionStatus; 13 | import org.springframework.transaction.support.DefaultTransactionDefinition; 14 | import org.springframework.util.ClassUtils; 15 | 16 | import java.lang.annotation.Annotation; 17 | import java.lang.reflect.Method; 18 | import java.util.Objects; 19 | import java.util.Stack; 20 | 21 | /** 22 | * 切面拦截器 23 | * 24 | * @author sobann 25 | */ 26 | public class DevBaseAnnotationsTransactionMethodInterceptor implements MethodInterceptor { 27 | 28 | private static final Class HANDLE_ANNOTATION = DevBaseMultiDataSourceTransactional.class; 29 | 30 | private final DevBaseDataSourceTransactionManagers devBaseDataSourceTransactionManagers; 31 | 32 | public DevBaseAnnotationsTransactionMethodInterceptor(DevBaseDataSourceTransactionManagers devBaseDataSourceTransactionManagers) { 33 | this.devBaseDataSourceTransactionManagers = devBaseDataSourceTransactionManagers; 34 | } 35 | 36 | @Override 37 | public Object invoke(MethodInvocation methodInvocation) throws Throwable { 38 | Annotation annotation = this.getAnnotation(methodInvocation); 39 | if (Objects.isNull(annotation)) { 40 | return methodInvocation.proceed(); 41 | } 42 | // 针对Transactional的解析,可以利用SpringTransactionAnnotationParser.parseTransactionAnnotation,多数据源的回滚异常不能使用Transactional,要定义在DevBaseMultiDataSourceTransactional中 43 | DevBaseMultiDataSourceTransactional multiDataSourceTransactional = (DevBaseMultiDataSourceTransactional) annotation; 44 | String[] transactionDbKeys = multiDataSourceTransactional.transactionDbKeys(); 45 | Stack> pairStack = new Stack<>(); 46 | try { 47 | 48 | for (String dbKey : transactionDbKeys) { 49 | DataSourceTransactionManager dataSourceTransactionManager = devBaseDataSourceTransactionManagers.get(dbKey); 50 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(getTransactionDefinition()); 51 | pairStack.push(new Pair<>(dataSourceTransactionManager, transactionStatus)); 52 | } 53 | Object proceed = methodInvocation.proceed(); 54 | System.err.println("No exception, ready to commit transaction..."); 55 | while (!pairStack.empty()) { 56 | Pair pair = pairStack.pop(); 57 | pair.getKey().commit(pair.getValue()); 58 | } 59 | return proceed; 60 | } catch (Exception e) { 61 | System.err.println("An exception occurs and the transaction is ready to be rolled back..."); 62 | while (!pairStack.empty()) { 63 | Pair pair = pairStack.pop(); 64 | pair.getKey().rollback(pair.getValue()); 65 | } 66 | throw new TransactionException(e); 67 | } 68 | } 69 | 70 | 71 | /** 72 | * 从方法或类上解析出DevBaseMultiDataSourceTransactional 73 | * 方法优先 74 | * 75 | * @param methodInvocation 76 | * @return 77 | */ 78 | protected Annotation getAnnotation(MethodInvocation methodInvocation) { 79 | DevBaseMultiDataSourceTransactional multiDataSourceTransactional = AnnotationUtils.findAnnotation(methodInvocation.getMethod(), HANDLE_ANNOTATION); 80 | if (multiDataSourceTransactional == null) { 81 | Class targetClass = methodInvocation.getThis().getClass(); 82 | Method method = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass); 83 | multiDataSourceTransactional = AnnotationUtils.findAnnotation(method, HANDLE_ANNOTATION); 84 | } 85 | return multiDataSourceTransactional; 86 | } 87 | 88 | 89 | /** 90 | * 获取事务定义,最基本的事务定义 91 | * 因为异常捕获是通过切点完成的,所以使用的是definition而不是对异常有条件的TransactionAttribute 92 | * 采用数据库的默认隔离级别 93 | * mysql 可重复读 94 | * oracle 读已提交 95 | * 96 | * @return 97 | */ 98 | private DefaultTransactionDefinition getTransactionDefinition() { 99 | //设置事务定义器 100 | DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 101 | // 非只读模式 102 | def.setReadOnly(false); 103 | // 事务隔离级别:采用数据库的默认隔离级别 104 | def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT); 105 | // 事务传播行为:创建或加入事务 106 | def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 107 | return def; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/transaction/aop/DevBaseMultiDatasourceTransactionAdvisor.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.transaction.aop; 2 | 3 | import com.cheese.db.spring.annotation.DevBaseMultiDataSourceTransactional; 4 | import com.cheese.db.spring.wrappers.DevBaseDataSourceTransactionManagers; 5 | import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor; 6 | import org.springframework.beans.BeansException; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.context.ApplicationContextAware; 9 | import org.springframework.core.annotation.AnnotationUtils; 10 | 11 | import java.lang.annotation.Annotation; 12 | import java.lang.reflect.Method; 13 | 14 | /** 15 | * 自定义切面行为 16 | * 先写一个简单的吧 17 | * 18 | * @author sobann 19 | */ 20 | public class DevBaseMultiDatasourceTransactionAdvisor extends StaticMethodMatcherPointcutAdvisor implements ApplicationContextAware { 21 | 22 | /** 23 | * 这里切面只针对@DevBaseMultiDataSourceTransactional 24 | * Transactional 25 | */ 26 | private static final Class[] TRANSACTION_ANNOTATION_CLASSES = new Class[]{DevBaseMultiDataSourceTransactional.class}; 27 | 28 | @Override 29 | public boolean matches(Method method, Class targetClass) { 30 | if (isTransactionAnnotationPresent(method)) { 31 | return true; 32 | } 33 | try { 34 | method = targetClass.getMethod(method.getName(), method.getParameterTypes()); 35 | return isTransactionAnnotationPresent(method) || isTransactionAnnotationPresent(targetClass); 36 | } catch (NoSuchMethodException ignored) { 37 | } 38 | return false; 39 | } 40 | 41 | /** 42 | * 如果类上标注了注解同样视为需要处理的方法 43 | * 44 | * @param targetClazz 45 | * @return 46 | */ 47 | private boolean isTransactionAnnotationPresent(Class targetClazz) { 48 | for (Class annClass : TRANSACTION_ANNOTATION_CLASSES) { 49 | Annotation a = AnnotationUtils.findAnnotation(targetClazz, annClass); 50 | if (a != null) { 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | /** 58 | * 方法上标注的方法若配置了权限注解则视为需要aop处理 59 | * 60 | * @param method 61 | * @return 62 | */ 63 | private boolean isTransactionAnnotationPresent(Method method) { 64 | for (Class annClass : TRANSACTION_ANNOTATION_CLASSES) { 65 | Annotation a = AnnotationUtils.findAnnotation(method, annClass); 66 | if (a != null) { 67 | return true; 68 | } 69 | } 70 | return false; 71 | } 72 | 73 | @Override 74 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 75 | DevBaseDataSourceTransactionManagers transactionManagers = applicationContext.getBean(DevBaseDataSourceTransactionManagers.class); 76 | setAdvice(new DevBaseAnnotationsTransactionMethodInterceptor(transactionManagers)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/transaction/aspectj/DevBaseMultiDataSourceTransactionalAspect.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.transaction.aspectj; 2 | 3 | import cn.hutool.core.lang.Pair; 4 | import com.cheese.db.spring.annotation.DevBaseMultiDataSourceTransactional; 5 | import com.cheese.db.spring.wrappers.DevBaseDataSourceTransactionManagers; 6 | import org.aspectj.lang.annotation.*; 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.context.ApplicationContextAware; 10 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 11 | import org.springframework.transaction.TransactionDefinition; 12 | import org.springframework.transaction.TransactionStatus; 13 | import org.springframework.transaction.support.DefaultTransactionDefinition; 14 | 15 | import java.util.Stack; 16 | 17 | /** 18 | * 多数据源事务管理器切面 19 | *

20 | * todo 切面类定义为一个接口 21 | * 整合spring的事务注解Transactional,事务的传播机制和隔离机制使用此注解内的内容 22 | * 23 | * 24 | * @author sobann 25 | */ 26 | @Aspect 27 | public class DevBaseMultiDataSourceTransactionalAspect implements ApplicationContextAware { 28 | 29 | private ApplicationContext applicationContext; 30 | 31 | /** 32 | * 线程本地变量:使用栈保存事务管理器和状态是为了达到后进先出的效果 33 | */ 34 | private static final ThreadLocal>> THREAD_LOCAL = new ThreadLocal<>(); 35 | 36 | 37 | /** 38 | * 切面 39 | */ 40 | @Pointcut("@annotation(com.cheese.db.spring.annotation.DevBaseMultiDataSourceTransactional)") 41 | public void pointcut() { 42 | } 43 | 44 | /** 45 | * 声明事务 46 | * 47 | * @param transactional 注解 48 | */ 49 | @Before("pointcut() && @annotation(transactional)") 50 | public void before(DevBaseMultiDataSourceTransactional transactional) { 51 | // 根据设置的事务名称按顺序声明,并放到ThreadLocal里 52 | System.err.println("Prepare to handle multi-source transaction management method..."); 53 | String[] transactionDbKeys = transactional.transactionDbKeys(); 54 | Stack> pairStack = new Stack<>(); 55 | DevBaseDataSourceTransactionManagers transactionManagers = applicationContext.getBean(DevBaseDataSourceTransactionManagers.class); 56 | 57 | for (String dbKey : transactionDbKeys) { 58 | DataSourceTransactionManager dataSourceTransactionManager = transactionManagers.get(dbKey); 59 | TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(getTransactionDefinition()); 60 | pairStack.push(new Pair<>(dataSourceTransactionManager, transactionStatus)); 61 | } 62 | THREAD_LOCAL.set(pairStack); 63 | } 64 | 65 | 66 | /** 67 | * 提交事务 68 | */ 69 | @AfterReturning("pointcut()") 70 | public void afterReturning() { 71 | System.err.println("No exception, ready to commit transaction..."); 72 | // 栈顶弹出(后进先出) 73 | Stack> pairStack = THREAD_LOCAL.get(); 74 | while (!pairStack.empty()) { 75 | Pair pair = pairStack.pop(); 76 | pair.getKey().commit(pair.getValue()); 77 | } 78 | THREAD_LOCAL.remove(); 79 | } 80 | 81 | /** 82 | * 回滚事务 83 | */ 84 | @AfterThrowing(value = "pointcut()") 85 | public void afterThrowing() { 86 | System.err.println("An exception occurs and the transaction is ready to be rolled back..."); 87 | // ※栈顶弹出(后进先出) 88 | Stack> pairStack = THREAD_LOCAL.get(); 89 | while (!pairStack.empty()) { 90 | Pair pair = pairStack.pop(); 91 | pair.getKey().rollback(pair.getValue()); 92 | } 93 | THREAD_LOCAL.remove(); 94 | } 95 | 96 | @Override 97 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 98 | this.applicationContext = applicationContext; 99 | } 100 | 101 | 102 | /** 103 | * 获取事务定义,最基本的事务定义 104 | * 因为异常捕获是通过切点完成的,所以使用的是definition而不是对异常有条件的TransactionAttribute 105 | * 采用数据库的默认隔离级别 106 | * mysql 可重复读 107 | * oracle 读已提交 108 | * 109 | * @return 110 | */ 111 | private DefaultTransactionDefinition getTransactionDefinition() { 112 | //设置事务定义器 113 | DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 114 | // 非只读模式 115 | def.setReadOnly(false); 116 | // 事务隔离级别:采用数据库的默认隔离级别 117 | def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT); 118 | // 事务传播行为:创建或加入事务 119 | def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 120 | return def; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/utils/SqlScriptUtils.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.utils; 2 | 3 | import org.springframework.util.StringUtils; 4 | 5 | /** 6 | * 使用 mybatis-plus 工具 7 | * 8 | * @author sobann 9 | */ 10 | public final class SqlScriptUtils extends StringUtils { 11 | 12 | private SqlScriptUtils() { 13 | // ignore 14 | } 15 | 16 | public static final String QUOTE = "\""; 17 | public static final String NEWLINE = "\n"; 18 | public static final String RIGHT_CHEV = ">"; 19 | public static final String HASH_LEFT_BRACE = "#{"; 20 | public static final String RIGHT_BRACE = "}"; 21 | public static final String DOLLAR_LEFT_BRACE = "${"; 22 | 23 | 24 | /** 25 | *

26 | * 获取 带 if 标签的脚本 27 | *

28 | * 29 | * @param sqlScript sql 脚本片段 30 | * @return if 脚本 31 | */ 32 | public static String convertIf(final String sqlScript, final String ifTest, boolean newLine) { 33 | String newSqlScript = sqlScript; 34 | if (newLine) { 35 | newSqlScript = NEWLINE + newSqlScript + NEWLINE; 36 | } 37 | return String.format("%s", ifTest, newSqlScript); 38 | } 39 | 40 | /** 41 | *

42 | * 获取 带 trim 标签的脚本 43 | *

44 | * 45 | * @param sqlScript sql 脚本片段 46 | * @param prefix 以...开头 47 | * @param suffix 以...结尾 48 | * @param prefixOverrides 干掉最前一个... 49 | * @param suffixOverrides 干掉最后一个... 50 | * @return trim 脚本 51 | */ 52 | public static String convertTrim(final String sqlScript, final String prefix, final String suffix, 53 | final String prefixOverrides, final String suffixOverrides) { 54 | StringBuilder sb = new StringBuilder("").toString(); 68 | } 69 | 70 | /** 71 | *

72 | * 生成 choose 标签的脚本 73 | *

74 | * 75 | * @param whenTest when 内 test 的内容 76 | * @param otherwise otherwise 内容 77 | * @return choose 脚本 78 | */ 79 | public static String convertChoose(final String whenTest, final String whenSqlScript, final String otherwise) { 80 | return "" + NEWLINE 81 | + "" + NEWLINE 83 | + "" + otherwise + "" + NEWLINE 84 | + ""; 85 | } 86 | 87 | /** 88 | *

89 | * 生成 foreach 标签的脚本 90 | *

91 | * 92 | * @param sqlScript foreach 内部的 sql 脚本 93 | * @param collection collection 94 | * @param index index 95 | * @param item item 96 | * @param separator separator 97 | * @return foreach 脚本 98 | */ 99 | public static String convertForeach(final String sqlScript, final String collection, final String index, 100 | final String item, final String separator) { 101 | StringBuilder sb = new StringBuilder("").toString(); 115 | } 116 | 117 | /** 118 | *

119 | * 生成 where 标签的脚本 120 | *

121 | * 122 | * @param sqlScript where 内部的 sql 脚本 123 | * @return where 脚本 124 | */ 125 | public static String convertWhere(final String sqlScript) { 126 | return "" + NEWLINE + sqlScript + NEWLINE + ""; 127 | } 128 | 129 | /** 130 | *

131 | * 生成 set 标签的脚本 132 | *

133 | * 134 | * @param sqlScript set 内部的 sql 脚本 135 | * @return set 脚本 136 | */ 137 | public static String convertSet(final String sqlScript) { 138 | return "" + NEWLINE + sqlScript + NEWLINE + ""; 139 | } 140 | 141 | /** 142 | *

143 | * 安全入参: #{入参} 144 | *

145 | * 146 | * @param param 入参 147 | * @return 脚本 148 | */ 149 | public static String safeParam(final String param) { 150 | return HASH_LEFT_BRACE + param + RIGHT_BRACE; 151 | } 152 | 153 | /** 154 | *

155 | * 非安全入参: ${入参} 156 | *

157 | * 158 | * @param param 入参 159 | * @return 脚本 160 | */ 161 | public static String unSafeParam(final String param) { 162 | return DOLLAR_LEFT_BRACE + param + RIGHT_BRACE; 163 | } 164 | } -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/DevBaseDataSourceTransactionManagers.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers; 2 | 3 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 4 | 5 | /** 6 | * 多数据源事务管理器 - spring 7 | * 8 | * @author sobann 9 | */ 10 | public interface DevBaseDataSourceTransactionManagers { 11 | 12 | void put(String dbKey, DataSourceTransactionManager dataSourceTransactionManager); 13 | 14 | DataSourceTransactionManager get(String dbKey); 15 | } 16 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/DevBaseDataSources.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers; 2 | 3 | import javax.sql.DataSource; 4 | import java.util.Map; 5 | 6 | /** 7 | * 多数据源 8 | * 9 | * @author sobann 10 | */ 11 | public interface DevBaseDataSources { 12 | 13 | Map getSources(); 14 | 15 | void put(String dbKey, DataSource dataSource); 16 | } 17 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/DevBaseSqlSessionFactories.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers; 2 | 3 | import org.apache.ibatis.session.SqlSessionFactory; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 多数据源会话工厂 9 | * 10 | * @author sobann 11 | */ 12 | public interface DevBaseSqlSessionFactories { 13 | 14 | Map getFactoryMap(); 15 | 16 | void put(String dbKey, SqlSessionFactory sqlSessionFactory); 17 | } 18 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/DevBaseSqlSessions.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers; 2 | 3 | import org.apache.ibatis.session.SqlSession; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * DevBaseSqlSessionTemplate包装 9 | * 10 | * @author sobann 11 | */ 12 | public interface DevBaseSqlSessions { 13 | 14 | Map getSqlSessions(); 15 | 16 | 17 | void put(String dbKey, SqlSession sqlSession); 18 | } 19 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/simple/DefaultDevBaseDataSourceTransactionManagers.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers.simple; 2 | 3 | import com.cheese.db.spring.wrappers.DevBaseDataSourceTransactionManagers; 4 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 5 | import org.springframework.util.Assert; 6 | 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * 多数据源事务管理器 - 默认实现 12 | * 13 | * @author sobann 14 | */ 15 | public class DefaultDevBaseDataSourceTransactionManagers implements DevBaseDataSourceTransactionManagers { 16 | 17 | private Map dataSourceTransactionManagerMap = new ConcurrentHashMap<>(); 18 | 19 | public Map getDataSourceTransactionManagerMap() { 20 | return dataSourceTransactionManagerMap; 21 | } 22 | 23 | public void setDataSourceTransactionManagerMap(Map dataSourceTransactionManagerMap) { 24 | this.dataSourceTransactionManagerMap = dataSourceTransactionManagerMap; 25 | } 26 | 27 | @Override 28 | public void put(String dbKey, DataSourceTransactionManager dataSourceTransactionManager) { 29 | this.dataSourceTransactionManagerMap.put(dbKey, dataSourceTransactionManager); 30 | } 31 | 32 | @Override 33 | public DataSourceTransactionManager get(String dbKey) { 34 | DataSourceTransactionManager transactionManager = this.dataSourceTransactionManagerMap.getOrDefault(dbKey, null); 35 | Assert.notNull(transactionManager, "error db key for transactionManager"); 36 | return transactionManager; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/simple/DefaultDevBaseDataSources.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers.simple; 2 | 3 | import com.cheese.db.spring.wrappers.DevBaseDataSources; 4 | 5 | import javax.sql.DataSource; 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * 多数据源 默认实现 11 | * 12 | * @author sobann 13 | */ 14 | public class DefaultDevBaseDataSources implements DevBaseDataSources { 15 | 16 | private Map sources = new ConcurrentHashMap<>(); 17 | 18 | @Override 19 | public Map getSources() { 20 | return sources; 21 | } 22 | 23 | public void setSources(Map sources) { 24 | this.sources = sources; 25 | } 26 | 27 | @Override 28 | public void put(String dbKey, DataSource dataSource) { 29 | this.sources.put(dbKey, dataSource); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/simple/DefaultDevBaseSqlSessionFactories.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers.simple; 2 | 3 | import com.cheese.db.spring.wrappers.DevBaseSqlSessionFactories; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * 多数据源会话工厂 默认实现 11 | * 12 | * @author sobann 13 | */ 14 | public class DefaultDevBaseSqlSessionFactories implements DevBaseSqlSessionFactories { 15 | private Map factoryMap = new ConcurrentHashMap<>(); 16 | 17 | @Override 18 | public Map getFactoryMap() { 19 | return factoryMap; 20 | } 21 | 22 | public void setFactoryMap(Map factoryMap) { 23 | this.factoryMap = factoryMap; 24 | } 25 | 26 | @Override 27 | public void put(String dbKey, SqlSessionFactory sqlSessionFactory) { 28 | this.factoryMap.put(dbKey, sqlSessionFactory); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cheese-db-spring/src/main/java/com/cheese/db/spring/wrappers/simple/DefaultDevBaseSqlSessions.java: -------------------------------------------------------------------------------- 1 | package com.cheese.db.spring.wrappers.simple; 2 | 3 | import com.cheese.db.spring.wrappers.DevBaseSqlSessions; 4 | import org.apache.ibatis.session.SqlSession; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | /** 10 | * DevBaseSqlSessionTemplate包装 11 | * 12 | * @author sobann 13 | */ 14 | public class DefaultDevBaseSqlSessions implements DevBaseSqlSessions { 15 | 16 | private Map sqlSessions = new ConcurrentHashMap<>(); 17 | 18 | @Override 19 | public Map getSqlSessions() { 20 | return sqlSessions; 21 | } 22 | 23 | public void setSqlSessions(Map sqlSessions) { 24 | this.sqlSessions = sqlSessions; 25 | } 26 | 27 | @Override 28 | public void put(String dbKey, SqlSession sqlSession) { 29 | this.sqlSessions.put(dbKey, sqlSession); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /doc/sql/cheese-repository-bus.sql: -------------------------------------------------------------------------------- 1 | 2 | SET NAMES utf8mb4; 3 | SET FOREIGN_KEY_CHECKS = 0; 4 | 5 | DROP TABLE IF EXISTS `dt_borrow_manage_borrow_apply`; 6 | 7 | CREATE TABLE `dt_borrow_manage_borrow_apply` ( 8 | `id` bigint NOT NULL COMMENT '唯一标识', 9 | `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请类型:1线上;2线下', 10 | `apply_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请编号', 11 | `geodata_id` bigint DEFAULT NULL COMMENT '申请文件元数据id', 12 | `apply_user` bigint DEFAULT NULL COMMENT '申请人id', 13 | `apply_reason` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '申请借阅原因', 14 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注', 15 | `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 16 | `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', 17 | `create_by` bigint DEFAULT NULL COMMENT '创建人id', 18 | `update_by` bigint DEFAULT NULL COMMENT '编辑者id', 19 | `status` tinyint(1) DEFAULT '0' COMMENT '业务状态:0申请中;1通过;2驳回;3拒绝', 20 | `is_deleted` tinyint unsigned DEFAULT '0' COMMENT '删除标记', 21 | PRIMARY KEY (`id`) USING BTREE 22 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='借阅信息-借阅申请'; 23 | 24 | INSERT INTO `hb_databank`.`dt_borrow_manage_borrow_apply` (`id`, `type`, `apply_code`, `geodata_id`, `apply_user`, `apply_reason`, `remark`, `create_time`, `update_time`, `create_by`, `update_by`, `status`, `is_deleted`) VALUES (1, 'online', 'TCC-20220103-001', 10086, 50, '因项目需要申请查看', '无', '2021-11-10 17:10:20', '2021-11-10 17:10:20', NULL, NULL, 0, 0); 25 | INSERT INTO `hb_databank`.`dt_borrow_manage_borrow_apply` (`id`, `type`, `apply_code`, `geodata_id`, `apply_user`, `apply_reason`, `remark`, `create_time`, `update_time`, `create_by`, `update_by`, `status`, `is_deleted`) VALUES (2, 'offline', 'TOF-20220103-00x', 10087, 51, '这是什么 申请一下', '无', '2023-06-07 15:21:11', '2023-06-07 07:21:10', NULL, NULL, 0, 0); 26 | INSERT INTO `hb_databank`.`dt_borrow_manage_borrow_apply` (`id`, `type`, `apply_code`, `geodata_id`, `apply_user`, `apply_reason`, `remark`, `create_time`, `update_time`, `create_by`, `update_by`, `status`, `is_deleted`) VALUES (3, 'offline', 'TOF-20230103-010', 10010, 50, '是资料啊 那就申请吧', '无', '2023-06-07 15:27:09', '2023-06-08 11:23:08', NULL, NULL, 0, 0); 27 | 28 | CREATE TABLE `dt_borrow_manage_borrow_apply_user_detail` ( 29 | `id` bigint NOT NULL COMMENT '唯一标识', 30 | `apply_id` bigint DEFAULT NULL COMMENT '申请id', 31 | `user_id` bigint DEFAULT NULL COMMENT '申请用户id', 32 | `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请用户名称', 33 | `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请用户手机号', 34 | `identity_card` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请用户身份证号', 35 | `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请用户邮箱', 36 | `unit_id` bigint DEFAULT NULL COMMENT '申请用户单位id', 37 | `unit_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '申请用户单位名称', 38 | `identity_card_font_file_id` bigint DEFAULT NULL COMMENT '身份证正面照片id,关联file服务,用于预览身份证照片', 39 | `identity_card_back_file_id` bigint DEFAULT NULL COMMENT '身份证反面照片id,关联file服务,用于预览身份证照片', 40 | `unit_support_file_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '单位出具的文件id,多个id使用","进行分割', 41 | `secret_cert_file_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '涉密证书文件id,多个id使用","进行分割', 42 | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '备注', 43 | `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 44 | `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', 45 | `create_by` bigint DEFAULT NULL COMMENT '创建人id', 46 | `update_by` bigint DEFAULT NULL COMMENT '编辑者id', 47 | `status` tinyint(1) DEFAULT '0' COMMENT '业务状态', 48 | `is_deleted` tinyint unsigned DEFAULT '0' COMMENT '删除标记', 49 | PRIMARY KEY (`id`) USING BTREE 50 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='借阅信息-借阅申请用户信息详情'; 51 | 52 | 53 | INSERT INTO `hb_databank`.`dt_borrow_manage_borrow_apply_user_detail` (`id`, `apply_id`, `user_id`, `name`, `phone`, `identity_card`, `email`, `unit_id`, `unit_name`, `identity_card_font_file_id`, `identity_card_back_file_id`, `unit_support_file_ids`, `secret_cert_file_ids`, `remark`, `create_time`, `update_time`, `create_by`, `update_by`, `status`, `is_deleted`) VALUES (100, 1, 50, 'cheese1', '13377778888', '422232199902030040', 'cheese@163.com', 20, 'cheese研究院', NULL, NULL, NULL, NULL, '无', '2023-06-07 15:44:57', '2023-06-07 07:45:06', NULL, NULL, 0, 0); -------------------------------------------------------------------------------- /doc/sql/cheese-repository-sys.sql: -------------------------------------------------------------------------------- 1 | SET NAMES utf8mb4; 2 | SET FOREIGN_KEY_CHECKS = 0; 3 | 4 | DROP TABLE IF EXISTS `sys_sql_config`; 5 | CREATE TABLE `sys_sql_config` ( 6 | `id` bigint(64) NOT NULL COMMENT '主键', 7 | `code` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '标识', 8 | `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '脚本语句', 9 | `dbkey` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据库标识', 10 | `dbtype` int(2) DEFAULT '0' COMMENT '数据库类型', 11 | `actiontype` int(2) DEFAULT '0' COMMENT '操作类型', 12 | `create_by` bigint(64) DEFAULT NULL COMMENT '创建人', 13 | `create_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 14 | `update_by` bigint(64) DEFAULT NULL COMMENT '修改人', 15 | `update_time` timestamp DEFAULT NULL COMMENT '修改时间', 16 | `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '备注', 17 | PRIMARY KEY (`id`) USING BTREE, 18 | UNIQUE KEY `code_Unique` (`code`) USING BTREE 19 | ) ENGINE=InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='sql脚本配置'; 20 | 21 | INSERT INTO `sys_sql_config` (`id`, `code`, `content`, `dbkey`, `dbtype`, `actiontype`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (50, 'INSERT_NEW_SYS_USER', 'INSERT INTO `sys_user` (`name`, `full_name`, `nick_name`, `email`, `telephone`, `password`, `salt`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) \nVALUES (#{ew.data.name}, #{ew.data.full_name}, #{ew.data.nick_name}, #{ew.data.email}, #{ew.data.telephone}, #{ew.data.password}, \'cheesesalt\', #{ew.data.status}, #{ew.data.create_by}, CURRENT_TIMESTAMP, NULL, NULL, #{ew.data.remark})', 'sys', 0, 1, 50, '2023-06-07 03:42:18', NULL, NULL, '无'); 22 | INSERT INTO `sys_sql_config` (`id`, `code`, `content`, `dbkey`, `dbtype`, `actiontype`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (51, 'UPDATE_BORROW_APPLY_DATA', 'UPDATE dt_borrow_manage_borrow_apply SET status = #{ew.data.status} WHERE id = #{ew.param.id}', 'bus', 0, 3, 50, '2023-06-07 03:42:18', NULL, NULL, '无'); 23 | INSERT INTO `sys_sql_config` (`id`, `code`, `content`, `dbkey`, `dbtype`, `actiontype`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (52, 'LOAD_BORROW_APPLY_INFO', 'SELECT \n apply.id AS id,\n apply.type AS type,\n apply.apply_code AS apply_code,\n apply.apply_user AS apply_user,\n user.name AS apply_user_name,\n user.phone AS apply_user_phone,\n user.email AS apply_user_email,\n apply.apply_reason AS apply_reason\nFROM dt_borrow_manage_borrow_apply AS apply\nLEFT JOIN dt_borrow_manage_borrow_apply_user_detail AS user ON apply.id = user.apply_id\n\n \n AND apply.id = #{ew.param.apply_id}\n \n \n AND apply.is_deleted = #{ew.param.is_deleted}\n \n\n', 'bus', 0, 0, 50, '2023-06-07 03:42:18', NULL, NULL, '无'); 24 | 25 | DROP TABLE IF EXISTS `sys_user`; 26 | CREATE TABLE `sys_user` ( 27 | `id` bigint(64) NOT NULL COMMENT '主键', 28 | `name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名', 29 | `full_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '全名', 30 | `nick_name` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '昵称', 31 | `email` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '邮箱/账号', 32 | `telephone` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '电话', 33 | `password` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '密码', 34 | `salt` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '盐', 35 | `status` tinyint(1) DEFAULT '1' COMMENT '帐号状态,0未激活,1启用,-1锁定', 36 | `create_by` bigint(64) DEFAULT NULL COMMENT '创建人', 37 | `create_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 38 | `update_by` bigint(64) DEFAULT NULL COMMENT '修改人', 39 | `update_time` timestamp DEFAULT NULL COMMENT '修改时间', 40 | `remark` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '备注', 41 | PRIMARY KEY (`id`) USING BTREE 42 | ) ENGINE=InnoDB AUTO_INCREMENT = 10086 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='系统用户'; 43 | 44 | --------------------------------------------------------------------------------