diff --git a/mybatis-flex-solon-plugin/README.md b/mybatis-flex-solon-plugin/README.md new file mode 100644 index 00000000..b4d2f4ce --- /dev/null +++ b/mybatis-flex-solon-plugin/README.md @@ -0,0 +1,137 @@ +```xml + + com.mybatis-flex + mybatis-flex-solon-plugin + +``` + +#### 1、描述 + +数据扩展插件,为 Solon Data 提供基于 mybatis-flex([代码仓库](https://gitee.com/mybatis-flex/mybatis-flex))的框架适配,以提供ORM支持。 + + +#### 2、强调多数据源支持 + +> Solon 的 ORM 框架都是基于多数据源理念进行适配的。关于 Solon 数据源概念的描述,可参考:[多数据源与动态数据源](https://solon.noear.org/article/353) + +* 强调多数据源的配置。例:demo.db1...,demo.db2... +* 强调带 name 的 DataSource Bean +* 强调使用 @Db("name") 的数据源注解 + + +@Db 可注入类型: + +| 支持类型 | 说明 | +| -------- | -------- | +| Mapper.class | 注入 Mapper。例:`@Db("db1") UserMapper userMapper` | +| FlexConfiguration | 注入 FlexConfiguration,一般仅用于配置。例:`@Db("db1") FlexConfiguration db1Cfg` | +| FlexGlobalConfig | 注入 FlexGlobalConfig,一般仅用于配置。例:`@Db("db1") FlexGlobalConfig db1Gc` | +| SqlSessionFactory | 注入 SqlSessionFactory。例:`@Db("db1") SqlSessionFactory db1` (不推荐直接使用) | + + +#### 3、数据源配置 + + +```yml +# 配置数据源 +demo.db1: + schema: rock + jdbcUrl: jdbc:mysql://localhost:3306/rock?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true + driverClassName: com.mysql.cj.jdbc.Driver + username: root + password: 123456 + +# 配置数据源对应的 mybatis 信息(要与 DataSource bean 的名字对上) +mybatis.db1: + typeAliases: #支持包名 或 类名(大写开头 或 *)//支持 ** 或 * 占位符 + - "demo4021.model" + - "demo4021.model.*" #这个表达式同上效果 + typeHandlers: #支持包名 或 类名(大写开头 或 *)//支持 ** 或 * 占位符 + - "demo4021.dso.mybaits.handler" + - "demo4021.dso.mybaits.handler.*" #这个表达式同上效果 + mappers: #支持包名 或 类名(大写开头 或 *)或 xml(.xml结尾)//支持 ** 或 * 占位符 + - "demo4021.**.mapper" + - "demo4021.**.mapper.*" #这个表达式同上效果 + - "classpath:demo4035/**/mapper.xml" + - "classpath:demo4035/**/mapping/*.xml" + configuration: #扩展配置(要与 FlexConfiguration 类的属性一一对应) + cacheEnabled: false + mapUnderscoreToCamelCase: true + globalConfig: #全局配置(要与 FlexGlobalConfig 类的属性一一对应) + banner: false + metaObjectHandler: "demo4035.dso.MetaObjectHandlerImpl" + + +# +#提示:使用 "**" 表达式时,范围要尽量小。不要用 "org.**"、"com.**" 之类的开头,范围太大了,会影响启动速度。 +# +``` + +> configuration、globalConfig 没有对应属性时,可用代码处理 + +##### Mapper 配置注意事项: + +* 通过 mapper 类包名配置。 xml 与 mapper 需同包同名 + +```yml +mybatis.db1.mappers: "demo4035.dso.mapper" +``` + +* 通过 xml 目录进行配置。xml 可以固定在一个资源目录下 + +```yml +mybatis.db1.mappers: "classpath:mybatis/db1/*.xml" +``` + + +#### 4、代码应用 + +```java +//配置数据源 +@Configuration +public class Config { + //此下的 db1 与 mybatis.db1 将对应在起来 //可以用 @Db("db1") 注入mapper + //typed=true,表示默认数据源。@Db 可不带名字注入 + @Bean(value = "db1", typed = true) + public DataSource db1(@Inject("${demo.db1}") HikariDataSource ds) { + return ds; + } + + //@Bean(value = "db2", typed = true) + //public DataSource db2(@Inject("${demo.db2}") HikariDataSource ds) { + // return ds; + //} + + //调整 db1 的配置(如:增加插件)// (配置可以解决的,不需要这块代码) + //@Bean + //public void db1_cfg(@Db("db1") FlexConfiguration cfg, + // @Db("db1") FlexGlobalConfig globalConfig) { + + // cfg.setCacheEnabled(false); + + //} +} + +//应用 +@ProxyComponent +public class AppService{ + //可用 @Db 或 @Db("db1") 注入 + @Db + AppMapper appMapper; //xml sql mapper + + //可用 @Db 或 @Db("db1") + @Db + BaseMapper appBaseMapper; //base mapper + + public void test(){ + App app1 = appMapper.getAppById(12); + App app2 = appBaseMapper.selectOneById(12); + } +} +``` + + + +**具体可参考:** + +[https://gitee.com/noear/solon-examples/tree/main/4.Solon-Data/demo4035-mybatisflex](https://gitee.com/noear/solon-examples/tree/main/4.Solon-Data/demo4035-mybatisflex) diff --git a/mybatis-flex-solon-plugin/pom.xml b/mybatis-flex-solon-plugin/pom.xml new file mode 100644 index 00000000..0e06eed1 --- /dev/null +++ b/mybatis-flex-solon-plugin/pom.xml @@ -0,0 +1,28 @@ + + + + parent + com.mybatis-flex + 1.0.8 + + 4.0.0 + + mybatis-flex-solon-plugin + + + + com.mybatis-flex + mybatis-flex-core + 1.0.8 + + + + org.noear + mybatis-solon-plugin + ${solon.version} + + + + \ No newline at end of file diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/SolonRowSessionManager.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/SolonRowSessionManager.java new file mode 100644 index 00000000..4606a75b --- /dev/null +++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/SolonRowSessionManager.java @@ -0,0 +1,22 @@ +package com.mybatisflex.solon; + +import com.mybatisflex.core.row.RowSessionManager; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; + +/** + * @author noear + * @since 2.2 + */ +public class SolonRowSessionManager implements RowSessionManager { + @Override + public SqlSession getSqlSession(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) { + return sqlSessionFactory.openSession(executorType); + } + + @Override + public void releaseSqlSession(SqlSession sqlSession, SqlSessionFactory sqlSessionFactory) { + sqlSession.close(); + } +} diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFactoryFlex.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFactoryFlex.java new file mode 100644 index 00000000..1c2376b9 --- /dev/null +++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFactoryFlex.java @@ -0,0 +1,24 @@ +package com.mybatisflex.solon.integration; + +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; +import org.apache.ibatis.solon.MybatisAdapter; +import org.apache.ibatis.solon.MybatisAdapterFactory; + +/** + * 适配器工厂 for mybatis-flex + * + * @author noear + * @since 2.2 + */ +public class MybatisAdapterFactoryFlex implements MybatisAdapterFactory { + @Override + public MybatisAdapter create(BeanWrap dsWrap) { + return new MybatisAdapterFlex(dsWrap); + } + + @Override + public MybatisAdapter create(BeanWrap dsWrap, Props dsProps) { + return new MybatisAdapterFlex(dsWrap, dsProps); + } +} diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java new file mode 100644 index 00000000..afa3a7d4 --- /dev/null +++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/MybatisAdapterFlex.java @@ -0,0 +1,104 @@ +package com.mybatisflex.solon.integration; + +import com.mybatisflex.core.FlexGlobalConfig; +import com.mybatisflex.core.datasource.FlexDataSource; +import com.mybatisflex.core.mybatis.FlexConfiguration; +import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.session.SqlSessionFactory; +import org.noear.solon.Utils; +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; +import org.noear.solon.core.VarHolder; +import org.apache.ibatis.solon.integration.MybatisAdapterDefault; + +import javax.sql.DataSource; + +/** + * 适配器 for mybatis-flex + * + * @author noear + * @since 2.2 + */ +public class MybatisAdapterFlex extends MybatisAdapterDefault { + FlexSqlSessionFactoryBuilder factoryBuilderPlus; + FlexGlobalConfig globalConfig; + + protected MybatisAdapterFlex(BeanWrap dsWrap) { + super(dsWrap); + + factoryBuilderPlus = new FlexSqlSessionFactoryBuilder(); + + dsWrap.context().getBeanAsync(FlexSqlSessionFactoryBuilder.class, bean -> { + factoryBuilderPlus = bean; + }); + } + + protected MybatisAdapterFlex(BeanWrap dsWrap, Props dsProps) { + super(dsWrap, dsProps); + + factoryBuilderPlus = new FlexSqlSessionFactoryBuilder(); + + dsWrap.context().getBeanAsync(FlexSqlSessionFactoryBuilder.class, bean -> { + factoryBuilderPlus = bean; + }); + } + + @Override + protected DataSource getDataSource() { + return new FlexDataSource(dsWrap.name(), dsWrap.raw()); + } + + @Override + protected void initConfiguration(Environment environment) { + + + //for configuration section + config = new FlexConfiguration(environment); + + Props cfgProps = dsProps.getProp("configuration"); + if (cfgProps.size() > 0) { + Utils.injectProperties(config, cfgProps); + } + + + //for globalConfig section + globalConfig = new FlexGlobalConfig(); + globalConfig.setKeyConfig(new FlexGlobalConfig.KeyConfig()); + + Props globalProps = dsProps.getProp("globalConfig"); + if (globalProps.size() > 0) { + //尝试配置注入 + Utils.injectProperties(globalConfig, globalProps); + } + globalConfig.setConfiguration(config); + FlexGlobalConfig.setConfig(environment.getId(), globalConfig); + } + + /** + * 获取全局配置 + * */ + public FlexGlobalConfig getGlobalConfig() { + return globalConfig; + } + + @Override + public SqlSessionFactory getFactory() { + if (factory == null) { + factory = factoryBuilderPlus.build(getConfiguration()); + } + + return factory; + } + + @Override + public void injectTo(VarHolder varH) { + super.injectTo(varH); + + //@Db("db1") SqlSessionFactory factory; + if (FlexGlobalConfig.class.isAssignableFrom(varH.getType())) { + varH.setValue(this.getGlobalConfig()); + return; + } + } +} diff --git a/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java new file mode 100644 index 00000000..70808431 --- /dev/null +++ b/mybatis-flex-solon-plugin/src/main/java/com/mybatisflex/solon/integration/XPluginImpl.java @@ -0,0 +1,36 @@ +package com.mybatisflex.solon.integration; + +import com.mybatisflex.core.FlexGlobalConfig; +import com.mybatisflex.core.row.Db; +import com.mybatisflex.solon.SolonRowSessionManager; +import org.noear.solon.core.AopContext; +import org.noear.solon.core.Plugin; +import org.apache.ibatis.solon.integration.MybatisAdapterManager; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author noear + * @since 2.2 + */ +public class XPluginImpl implements Plugin { + @Override + public void start(AopContext context) throws Throwable { + // + // 此插件的 solon.plugin.priority 会大于 mybatis-solon-plugin 的值 + // + MybatisAdapterManager.setAdapterFactory(new MybatisAdapterFactoryFlex()); + + dbConfiguration(); + } + + private void dbConfiguration(){ + FlexGlobalConfig defaultConfig = FlexGlobalConfig.getDefaultConfig(); + if (defaultConfig == null){ + Logger.getLogger(Db.class.getName()).log(Level.WARNING,"Cannot get FlexGlobalConfig instance, Perhaps the dataSource config error."); + }else { + Db.invoker().setRowSessionManager(new SolonRowSessionManager()); + } + } +} diff --git a/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties b/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties new file mode 100644 index 00000000..8e22aec1 --- /dev/null +++ b/mybatis-flex-solon-plugin/src/main/resources/META-INF/solon/mybatis-flex-solon-plugin.properties @@ -0,0 +1,2 @@ +solon.plugin=com.mybatisflex.solon.integration.XPluginImpl +solon.plugin.priority=3 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 03dbc216..06c03217 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ mybatis-flex-core mybatis-flex-spring mybatis-flex-spring-boot-starter + mybatis-flex-solon-plugin mybatis-flex-test @@ -63,6 +64,7 @@ 5.3.25 2.7.9 + 2.2.10 4.13.2