diff --git a/mybatis-flex-annotation/pom.xml b/mybatis-flex-annotation/pom.xml index 860a4bab..95cc69ad 100644 --- a/mybatis-flex-annotation/pom.xml +++ b/mybatis-flex-annotation/pom.xml @@ -36,9 +36,9 @@ - - target/generated-sources - + + + diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/MybatisFlexBootstrap.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/MybatisFlexBootstrap.java index 858edd7e..51e65df6 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/MybatisFlexBootstrap.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/MybatisFlexBootstrap.java @@ -16,7 +16,6 @@ package com.mybatisflex.core; import com.mybatisflex.core.datasource.RoutingDataSource; -import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder; import org.apache.ibatis.logging.Log; @@ -64,7 +63,6 @@ public class MybatisFlexBootstrap { protected Configuration configuration; protected List> mappers; - protected DbType dbType; protected SqlSessionFactory sqlSessionFactory; protected Class logImpl; @@ -115,7 +113,7 @@ public class MybatisFlexBootstrap { transactionFactory = new JdbcTransactionFactory(); } - Environment environment = new Environment(environmentId, transactionFactory, new RoutingDataSource(environmentId, dataSource)); + Environment environment = new Environment(environmentId, transactionFactory, dataSource); configuration = new FlexConfiguration(environment); } @@ -126,8 +124,6 @@ public class MybatisFlexBootstrap { //init sqlSessionFactory this.sqlSessionFactory = new FlexSqlSessionFactoryBuilder().build(configuration); - //init dbType - this.dbType = FlexGlobalConfig.getConfig(environmentId).getDbType(); //init mappers if (mappers != null) { @@ -234,6 +230,18 @@ public class MybatisFlexBootstrap { return this; } + public MybatisFlexBootstrap addDataSource(String dataSourceKey, DataSource dataSource) { + if (this.dataSource == null) { + this.dataSource = new RoutingDataSource(dataSourceKey, dataSource); + } else if (this.dataSource instanceof RoutingDataSource) { + ((RoutingDataSource) this.dataSource).addDataSource(dataSourceKey, dataSource); + } else { + this.dataSource = new RoutingDataSource("default", this.dataSource); + ((RoutingDataSource) this.dataSource).addDataSource(dataSourceKey, dataSource); + } + return this; + } + public Configuration getConfiguration() { return configuration; } @@ -249,15 +257,6 @@ public class MybatisFlexBootstrap { } - public DbType getDbType() { - return dbType; - } - - public MybatisFlexBootstrap setDbType(DbType dbType) { - this.dbType = dbType; - return this; - } - public SqlSessionFactory getSqlSessionFactory() { return sqlSessionFactory; } diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceBuilder.java similarity index 99% rename from mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceBuilder.java rename to mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceBuilder.java index 2afdd36d..06136708 100644 --- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceBuilder.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mybatisflex.spring.boot; +package com.mybatisflex.core.datasource; import com.mybatisflex.core.table.ConvertUtil; import com.mybatisflex.core.util.StringUtil; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java index afa83631..c70ba90a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java @@ -21,22 +21,22 @@ public class DataSourceKey { private static ThreadLocal keyThreadLocal = new ThreadLocal<>(); - public static void use(String environmentId) { - keyThreadLocal.set(environmentId); + public static void use(String dataSourceKey) { + keyThreadLocal.set(dataSourceKey); } - public static T use(String environmentId, Supplier supplier) { + public static T use(String dataSourceKey, Supplier supplier) { try { - use(environmentId); + use(dataSourceKey); return supplier.get(); } finally { clear(); } } - public static void use(String environmentId, Runnable runnable) { + public static void use(String dataSourceKey, Runnable runnable) { try { - use(environmentId); + use(dataSourceKey); runnable.run(); } finally { clear(); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/RoutingDataSource.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/RoutingDataSource.java index 1e5d1d2b..b021c6e9 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/RoutingDataSource.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/RoutingDataSource.java @@ -15,6 +15,8 @@ */ package com.mybatisflex.core.datasource; +import com.mybatisflex.core.dialect.DbType; +import com.mybatisflex.core.dialect.DbTypeUtil; import com.mybatisflex.core.util.StringUtil; import javax.sql.DataSource; @@ -25,13 +27,23 @@ import java.util.Map; public class RoutingDataSource extends AbstractDataSource { - private static Map dataSourceMap = new HashMap<>(); + private final Map dataSourceMap = new HashMap<>(); + private final Map dbTypeHashMap = new HashMap<>(); + private final DataSource defaultDataSource; - private DataSource delegate; + public RoutingDataSource(String dataSourceKey, DataSource dataSource) { + this.defaultDataSource = dataSource; + dataSourceMap.put(dataSourceKey, dataSource); + dbTypeHashMap.put(dataSourceKey, DbTypeUtil.getDbType(dataSource)); + } - public RoutingDataSource(String environmentId, DataSource delegate) { - this.delegate = delegate; - dataSourceMap.put(environmentId, delegate); + public void addDataSource(String dataSourceKey, DataSource dataSource) { + dataSourceMap.put(dataSourceKey, dataSource); + dbTypeHashMap.put(dataSourceKey, DbTypeUtil.getDbType(dataSource)); + } + + public DbType getDbType(String dataSourceKey){ + return dbTypeHashMap.get(dataSourceKey); } @Override @@ -44,22 +56,33 @@ public class RoutingDataSource extends AbstractDataSource { return getDataSource().getConnection(username, password); } + @Override + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface.isInstance(this)) { + return (T) this; + } + return getDataSource().unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return (iface.isInstance(this) || getDataSource().isWrapperFor(iface)); + } + private DataSource getDataSource() { - DataSource dataSource = delegate; + DataSource dataSource = defaultDataSource; if (dataSourceMap.size() > 1) { - String environmentId = DataSourceKey.get(); - if (StringUtil.isNotBlank(environmentId)) { - dataSource = dataSourceMap.get(environmentId); + String dataSourceKey = DataSourceKey.get(); + if (StringUtil.isNotBlank(dataSourceKey)) { + dataSource = dataSourceMap.get(dataSourceKey); if (dataSource == null) { - throw new IllegalStateException("Cannot get target DataSource for environmentId [" + environmentId + "]"); + throw new IllegalStateException("Cannot get target DataSource for dataSourceKey [" + dataSourceKey + "]"); } } } return dataSource; } - public DataSource getDelegate() { - return delegate; - } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java index 6dc8e753..7ef35fd0 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java @@ -16,6 +16,12 @@ package com.mybatisflex.core.dialect; +import com.mybatisflex.core.util.StringUtil; + +import javax.sql.DataSource; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.SQLException; import java.util.regex.Pattern; /** @@ -24,6 +30,56 @@ import java.util.regex.Pattern; public class DbTypeUtil { + /** + * 获取当前配置的 DbType + */ + public static DbType getDbType(DataSource dataSource) { + String jdbcUrl = getJdbcUrl(dataSource); + + if (StringUtil.isNotBlank(jdbcUrl)) { + return parseDbType(jdbcUrl); + } + + throw new IllegalStateException("Cannot get dataSource jdbcUrl: " + dataSource.getClass().getName()); + } + + /** + * 通过数据源中获取 jdbc 的 url 配置 + * 符合 HikariCP, druid, c3p0, DBCP, beecp 数据源框架 以及 MyBatis UnpooledDataSource 的获取规则 + * UnpooledDataSource 参考 @{@link UnpooledDataSource#getUrl()} + * + * @return jdbc url 配置 + */ + private static String getJdbcUrl(DataSource dataSource) { + String[] methodNames = new String[]{"getUrl", "getJdbcUrl"}; + for (String methodName : methodNames) { + try { + Method method = dataSource.getClass().getMethod(methodName); + return (String) method.invoke(dataSource); + } catch (Exception e) { + //ignore + } + } + + Connection connection = null; + try { + connection = dataSource.getConnection(); + return connection.getMetaData().getURL(); + } catch (Exception e) { + //ignore + } finally { + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + } + } + } + + return null; + } + + /** * 参考 druid 和 MyBatis-plus 的 JdbcUtils * {@link com.alibaba.druid.util.JdbcUtils#getDbType(String, String)} @@ -32,7 +88,7 @@ public class DbTypeUtil { * @param jdbcUrl jdbcURL * @return 返回数据库类型 */ - public static DbType parseDbType(String jdbcUrl) { + private static DbType parseDbType(String jdbcUrl) { jdbcUrl = jdbcUrl.toLowerCase(); if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:")) { return DbType.MYSQL; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexSqlSessionFactoryBuilder.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexSqlSessionFactoryBuilder.java index 46376b2d..5ab49f63 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexSqlSessionFactoryBuilder.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexSqlSessionFactoryBuilder.java @@ -19,20 +19,14 @@ import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.dialect.DbTypeUtil; import com.mybatisflex.core.exception.FlexExceptions; -import com.mybatisflex.core.util.StringUtil; -import org.apache.ibatis.datasource.unpooled.UnpooledDataSource; import org.apache.ibatis.exceptions.ExceptionFactory; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; -import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.SQLException; import java.util.Properties; public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder { @@ -64,8 +58,7 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder { } SqlSessionFactory sessionFactory = super.build(configuration); - - DbType dbType = getDbType(configuration); + DbType dbType = DbTypeUtil.getDbType(configuration.getEnvironment().getDataSource()); //设置全局配置的 sessionFactory 和 dbType initGlobalConfig(configuration, sessionFactory, dbType); @@ -91,55 +84,5 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder { } - /** - * 获取当前配置的 DbType - */ - private DbType getDbType(Configuration configuration) { - DataSource dataSource = configuration.getEnvironment().getDataSource(); - String jdbcUrl = getJdbcUrl(dataSource); - - if (StringUtil.isNotBlank(jdbcUrl)) { - return DbTypeUtil.parseDbType(jdbcUrl); - } - - throw new IllegalStateException("Cannot get dataSource jdbcUrl: " + dataSource.getClass().getName()); - } - - /** - * 通过数据源中获取 jdbc 的 url 配置 - * 符合 HikariCP, druid, c3p0, DBCP, beecp 数据源框架 以及 MyBatis UnpooledDataSource 的获取规则 - * UnpooledDataSource 参考 @{@link UnpooledDataSource#getUrl()} - * TODO: 2023/2/18 可能极个别特殊的数据源无法获取 JDBC 配置的 URL - * - * @return jdbc url 配置 - */ - private String getJdbcUrl(DataSource dataSource) { - String[] methodNames = new String[]{"getUrl", "getJdbcUrl"}; - for (String methodName : methodNames) { - try { - Method method = dataSource.getClass().getMethod(methodName); - return (String) method.invoke(dataSource); - } catch (Exception e) { - //ignore - } - } - - Connection connection = null; - try { - connection = dataSource.getConnection(); - return connection.getMetaData().getURL(); - } catch (Exception e) { - //ignore - } finally { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - } - } - } - - return null; - } } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java index 13a129d9..ddd9b3ab 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java @@ -18,22 +18,32 @@ package com.mybatisflex.core.mybatis; import com.mybatisflex.annotation.UseDataSource; import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.datasource.DataSourceKey; +import com.mybatisflex.core.datasource.RoutingDataSource; import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.dialect.DialectFactory; +import com.mybatisflex.core.row.RowMapper; +import com.mybatisflex.core.table.TableInfo; +import com.mybatisflex.core.table.TableInfoFactory; import com.mybatisflex.core.util.StringUtil; import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.util.MapUtil; +import javax.sql.DataSource; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class MapperInvocationHandler implements InvocationHandler { + private static final String NONE_KEY = "!NONE"; + private static final Map methodDataSourceKeyMap = new ConcurrentHashMap<>(); - private Object mapper; - private Configuration configuration; + private final Object mapper; + private final DataSource dataSource; public MapperInvocationHandler(Object mapper, Configuration configuration) { this.mapper = mapper; - this.configuration = configuration; + this.dataSource = configuration.getEnvironment().getDataSource(); } @@ -43,25 +53,26 @@ public class MapperInvocationHandler implements InvocationHandler { boolean clearDbType = false; try { //获取用户动态指定,由用户指定数据源,则应该有用户清除 - String environmentId = DataSourceKey.get(); + String dataSourceKey = DataSourceKey.get(); - //通过 方法 的注解去获取 - if (StringUtil.isBlank(environmentId)) { - environmentId = getMethodEnvironmentId(method); - if (StringUtil.isNotBlank(environmentId)) { - DataSourceKey.use(environmentId); + if (StringUtil.isBlank(dataSourceKey)) { + String methodKey = getMethodDataSource(method, proxy); + if (!NONE_KEY.equals(methodKey)) { + dataSourceKey = methodKey; + DataSourceKey.use(dataSourceKey); clearDsKey = true; } } - if (StringUtil.isBlank(environmentId)) { - environmentId = configuration.getEnvironment().getId(); - } - //优先获取用户自己配置的 dbType DbType dbType = DialectFactory.getHintDbType(); if (dbType == null) { - dbType = FlexGlobalConfig.getConfig(environmentId).getDbType(); + if (dataSourceKey != null && dataSource instanceof RoutingDataSource) { + dbType = ((RoutingDataSource) dataSource).getDbType(dataSourceKey); + } + if (dbType == null) { + dbType = FlexGlobalConfig.getDefaultConfig().getDbType(); + } DialectFactory.setHintDbType(dbType); clearDbType = true; } @@ -77,9 +88,26 @@ public class MapperInvocationHandler implements InvocationHandler { } - private String getMethodEnvironmentId(Method method) { - UseDataSource useDataSource = method.getAnnotation(UseDataSource.class); - return useDataSource != null ? useDataSource.value() : null; + private static String getMethodDataSource(Method method, Object proxy) { + return MapUtil.computeIfAbsent(methodDataSourceKeyMap, method, method1 -> { + UseDataSource useDataSource = method1.getAnnotation(UseDataSource.class); + if (useDataSource != null && StringUtil.isNotBlank(useDataSource.value())) { + return useDataSource.value(); + } + + Class[] interfaces = proxy.getClass().getInterfaces(); + if (interfaces[0] != RowMapper.class) { + TableInfo tableInfo = TableInfoFactory.ofMapperClass(interfaces[0]); + if (tableInfo != null) { + String dataSourceKey = tableInfo.getDataSource(); + if (StringUtil.isNotBlank(dataSourceKey)) { + return dataSourceKey; + } + } + } + return NONE_KEY; + }); } + } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowMapperInvoker.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowMapperInvoker.java index d1e7c71c..9db53e63 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowMapperInvoker.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowMapperInvoker.java @@ -15,8 +15,6 @@ */ package com.mybatisflex.core.row; -import com.mybatisflex.core.FlexGlobalConfig; -import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import org.apache.ibatis.executor.BatchResult; @@ -32,12 +30,10 @@ import java.util.function.Function; public class RowMapperInvoker { private final SqlSessionFactory sqlSessionFactory; - private final DbType dbType; private RowSessionManager rowSessionManager = RowSessionManager.DEFAULT; public RowMapperInvoker(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; - this.dbType = FlexGlobalConfig.getConfig(sqlSessionFactory.getConfiguration()).getDbType(); } public RowSessionManager getRowSessionManager() { diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java index a82fb403..192c74f0 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfoFactory.java @@ -66,7 +66,7 @@ public class TableInfoFactory { public static TableInfo ofMapperClass(Class mapperClass) { return MapUtil.computeIfAbsent(tableInfoMap, mapperClass, key -> { - Class entityClass = getEntityClass(key); + Class entityClass = getEntityClass(mapperClass); return entityClass != null ? ofEntityClass(entityClass) : null; }); } diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/test/Account.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Account.java similarity index 97% rename from mybatis-flex-core/src/test/java/com/mybatisflex/test/Account.java rename to mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Account.java index 1bdf35c6..1ec065d0 100644 --- a/mybatis-flex-core/src/test/java/com/mybatisflex/test/Account.java +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Account.java @@ -1,4 +1,4 @@ -package com.mybatisflex.test; +package com.mybatisflex.coretest; import com.mybatisflex.annotation.Column; import com.mybatisflex.annotation.Id; diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/test/AccountSqlTester.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/AccountSqlTester.java similarity index 98% rename from mybatis-flex-core/src/test/java/com/mybatisflex/test/AccountSqlTester.java rename to mybatis-flex-core/src/test/java/com/mybatisflex/coretest/AccountSqlTester.java index 599f3322..65bd1bde 100644 --- a/mybatis-flex-core/src/test/java/com/mybatisflex/test/AccountSqlTester.java +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/AccountSqlTester.java @@ -1,4 +1,4 @@ -package com.mybatisflex.test; +package com.mybatisflex.coretest; import com.mybatisflex.core.dialect.CommonsDialectImpl; import com.mybatisflex.core.dialect.IDialect; @@ -13,8 +13,8 @@ import org.junit.Test; import java.util.Arrays; import static com.mybatisflex.core.query.QueryMethods.*; -import static com.mybatisflex.test.table.Tables.ACCOUNT; -import static com.mybatisflex.test.table.Tables.ARTICLE; +import static com.mybatisflex.coretest.table.Tables.ACCOUNT; +import static com.mybatisflex.coretest.table.Tables.ARTICLE; public class AccountSqlTester { diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/test/Article.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Article.java similarity index 98% rename from mybatis-flex-core/src/test/java/com/mybatisflex/test/Article.java rename to mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Article.java index 73858f6f..9262d8da 100644 --- a/mybatis-flex-core/src/test/java/com/mybatisflex/test/Article.java +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/Article.java @@ -1,4 +1,4 @@ -package com.mybatisflex.test; +package com.mybatisflex.coretest; import com.mybatisflex.annotation.Column; import com.mybatisflex.annotation.Id; diff --git a/mybatis-flex-core/src/test/java/com/mybatisflex/test/ArticleSqlTester.java b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/ArticleSqlTester.java similarity index 97% rename from mybatis-flex-core/src/test/java/com/mybatisflex/test/ArticleSqlTester.java rename to mybatis-flex-core/src/test/java/com/mybatisflex/coretest/ArticleSqlTester.java index 4605b1ac..553e39df 100644 --- a/mybatis-flex-core/src/test/java/com/mybatisflex/test/ArticleSqlTester.java +++ b/mybatis-flex-core/src/test/java/com/mybatisflex/coretest/ArticleSqlTester.java @@ -1,4 +1,4 @@ -package com.mybatisflex.test; +package com.mybatisflex.coretest; import com.mybatisflex.core.dialect.CommonsDialectImpl; import com.mybatisflex.core.dialect.IDialect; @@ -8,7 +8,7 @@ import com.mybatisflex.core.table.TableInfoFactory; import com.mybatisflex.core.util.CollectionUtil; import org.junit.Test; -import static com.mybatisflex.test.table.Tables.ARTICLE; +import static com.mybatisflex.coretest.table.Tables.ARTICLE; public class ArticleSqlTester { diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java index ddebe444..4a0cdc00 100644 --- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java +++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java @@ -15,36 +15,19 @@ */ package com.mybatisflex.spring.boot; +import com.mybatisflex.core.datasource.DataSourceBuilder; import com.mybatisflex.core.datasource.RoutingDataSource; -import com.mybatisflex.spring.FlexSqlSessionFactoryBean; -import org.apache.ibatis.mapping.DatabaseIdProvider; -import org.apache.ibatis.plugin.Interceptor; -import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.type.TypeHandler; import org.mybatis.spring.SqlSessionFactoryBean; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import javax.sql.DataSource; -import java.beans.PropertyDescriptor; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; /** @@ -54,116 +37,35 @@ import java.util.stream.Stream; @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class}) @ConditionalOnPropertyEmpty("spring.datasource.url") @EnableConfigurationProperties(MybatisFlexProperties.class) -@AutoConfigureAfter({MybatisLanguageDriverAutoConfiguration.class}) @AutoConfigureBefore({DataSourceAutoConfiguration.class}) -public class MultiDataSourceAutoConfiguration extends MybatisFlexAutoConfiguration { +public class MultiDataSourceAutoConfiguration { - private List sqlSessionFactories = new ArrayList<>(); - private List dataSources = new ArrayList<>(); + private Map> dataSourceProperties; - public MultiDataSourceAutoConfiguration(MybatisFlexProperties properties - , ObjectProvider interceptorsProvider - , ObjectProvider typeHandlersProvider - , ObjectProvider languageDriversProvider - , ResourceLoader resourceLoader - , ObjectProvider databaseIdProvider - , ObjectProvider> configurationCustomizersProvider - , ObjectProvider> sqlSessionFactoryBeanCustomizers) { - super(properties, interceptorsProvider, typeHandlersProvider, languageDriversProvider, resourceLoader, databaseIdProvider, configurationCustomizersProvider, sqlSessionFactoryBeanCustomizers); - - initDataSources(properties.getDatasource()); - } - - - private void initDataSources(Map> datasourceMap) { - if (datasourceMap != null) { - datasourceMap.forEach((s, dsp) -> { - DataSource dataSource = new DataSourceBuilder(dsp).build(); - SqlSessionFactory sqlSessionFactory = buildSqlSessionFactory(s, dataSource); - sqlSessionFactories.add(sqlSessionFactory); - }); - } - } - - - public SqlSessionFactory buildSqlSessionFactory(String environmentId, DataSource dataSource) { -// SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); - SqlSessionFactoryBean factory = new FlexSqlSessionFactoryBean(); - - dataSource = new RoutingDataSource(environmentId, dataSource); - dataSources.add(dataSource); - - factory.setDataSource(new RoutingDataSource(environmentId, dataSource)); -// factory.setEnvironment(environmentId); - - if (properties.getConfiguration() == null || properties.getConfiguration().getVfsImpl() == null) { - factory.setVfs(SpringBootVFS.class); - } - if (StringUtils.hasText(this.properties.getConfigLocation())) { - factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); - } - applyConfiguration(factory); - if (this.properties.getConfigurationProperties() != null) { - factory.setConfigurationProperties(this.properties.getConfigurationProperties()); - } - if (!ObjectUtils.isEmpty(this.interceptors)) { - factory.setPlugins(this.interceptors); - } - if (this.databaseIdProvider != null) { - factory.setDatabaseIdProvider(this.databaseIdProvider); - } - if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { - factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); - } - if (this.properties.getTypeAliasesSuperType() != null) { - factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); - } - if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { - factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); - } - if (!ObjectUtils.isEmpty(this.typeHandlers)) { - factory.setTypeHandlers(this.typeHandlers); - } - Resource[] mapperLocations = this.properties.resolveMapperLocations(); - if (!ObjectUtils.isEmpty(mapperLocations)) { - factory.setMapperLocations(mapperLocations); - } - Set factoryPropertyNames = Stream - .of(new BeanWrapperImpl(SqlSessionFactoryBean.class).getPropertyDescriptors()).map(PropertyDescriptor::getName) - .collect(Collectors.toSet()); - Class defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); - if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) { - // Need to mybatis-spring 2.0.2+ - factory.setScriptingLanguageDrivers(this.languageDrivers); - if (defaultLanguageDriver == null && this.languageDrivers.length == 1) { - defaultLanguageDriver = this.languageDrivers[0].getClass(); - } - } - if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) { - // Need to mybatis-spring 2.0.2+ - factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver); - } - applySqlSessionFactoryBeanCustomizers(factory); - try { - return factory.getObject(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - - @Bean - @ConditionalOnMissingBean - public SqlSessionFactory sqlSessionFactory() { - return sqlSessionFactories.isEmpty() ? null : sqlSessionFactories.get(0); + public MultiDataSourceAutoConfiguration(MybatisFlexProperties properties) { + dataSourceProperties = properties.getDatasource(); } @Bean @ConditionalOnMissingBean public DataSource dataSource() { - return dataSources.isEmpty() ? null : dataSources.get(0); + + RoutingDataSource routingDataSource = null; + + if (dataSourceProperties != null && !dataSourceProperties.isEmpty()) { + for (String key : dataSourceProperties.keySet()) { + DataSource dataSource = new DataSourceBuilder(dataSourceProperties.get(key)).build(); + if (routingDataSource == null) { + routingDataSource = new RoutingDataSource(key, dataSource); + } else { + routingDataSource.addDataSource(key, dataSource); + } + } + } + + return routingDataSource; } diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java index d835e693..da173498 100644 --- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java +++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexAutoConfiguration.java @@ -40,7 +40,6 @@ import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -81,7 +80,6 @@ import java.util.stream.Stream; */ @org.springframework.context.annotation.Configuration(proxyBeanMethods = false) @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class}) -@ConditionalOnProperty("spring.datasource.url") @ConditionalOnSingleCandidate(DataSource.class) @EnableConfigurationProperties(MybatisFlexProperties.class) @AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class}) diff --git a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/FlexSqlSessionFactoryBean.java b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/FlexSqlSessionFactoryBean.java index cc183bcc..945f39c0 100644 --- a/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/FlexSqlSessionFactoryBean.java +++ b/mybatis-flex-spring/src/main/java/com/mybatisflex/spring/FlexSqlSessionFactoryBean.java @@ -16,7 +16,6 @@ package com.mybatisflex.spring; import com.mybatisflex.core.FlexConsts; -import com.mybatisflex.core.datasource.RoutingDataSource; import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder; import com.mybatisflex.core.mybatis.FlexXMLConfigBuilder; @@ -583,8 +582,7 @@ public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean } targetConfiguration.setEnvironment(new Environment(this.environment, - this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory, - dataSource instanceof RoutingDataSource ? dataSource : new RoutingDataSource(environment, this.dataSource))); + this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory, dataSource)); if (this.mapperLocations != null) { if (this.mapperLocations.length == 0) { diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java index 8abfe04a..86d5f602 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/EntityTestStarter.java @@ -44,8 +44,12 @@ public class EntityTestStarter { // System.out.println(account); AccountMapper accountMapper = bootstrap.getMapper(AccountMapper.class); - Account account = accountMapper.selectOneById(1); - System.out.println(account); + + for (int i = 0; i < 100; i++) { + Account account = accountMapper.selectOneById(1); + } + +// System.out.println(account); // // List allAccount = bootstrap.execute(AccountMapper.class, accountMapper -> // accountMapper.selectListByQuery(QueryWrapper.create()));