diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/UseDataSource.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/UseDataSource.java
new file mode 100644
index 00000000..b4386fe2
--- /dev/null
+++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/UseDataSource.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.annotation;
+
+import java.lang.annotation.*;
+
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface UseDataSource {
+
+ /**
+ * 使用哪个数据源,配置的是 Mybatis 的 environmentId
+ */
+ String value();
+
+
+}
\ No newline at end of file
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java
index ddec3b00..ccf318e0 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/FlexConsts.java
@@ -19,6 +19,7 @@ package com.mybatisflex.core;
* Mybatis-Flex 可能用到的静态常量
*/
public class FlexConsts {
+ public static final String NAME = "MyBatis-Flex";
public static final String VERSION = "1.0.5";
public static final String DEFAULT_PRIMARY_FIELD = "id";
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 c48d1ed6..e59c64d8 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
@@ -15,8 +15,8 @@
*/
package com.mybatisflex.core;
+import com.mybatisflex.core.datasource.RoutingDataSource;
import com.mybatisflex.core.dialect.DbType;
-import com.mybatisflex.core.dialect.DialectFactory;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
import org.apache.ibatis.logging.Log;
@@ -57,7 +57,7 @@ public class MybatisFlexBootstrap {
protected final AtomicBoolean started = new AtomicBoolean(false);
- protected String environmentId = "mybatis-flex";
+ protected String environmentId;
protected TransactionFactory transactionFactory;
protected DataSource dataSource;
@@ -74,7 +74,8 @@ public class MybatisFlexBootstrap {
* 虽然提供了 getInstance,但也允许用户进行实例化,
* 用于创建多个 MybatisFlexBootstrap 实例达到管理多数据源的目的
*/
- public MybatisFlexBootstrap() {
+ public MybatisFlexBootstrap(String environmentId) {
+ this.environmentId = environmentId;
}
private static volatile MybatisFlexBootstrap instance;
@@ -83,7 +84,7 @@ public class MybatisFlexBootstrap {
if (instance == null) {
synchronized (MybatisFlexBootstrap.class) {
if (instance == null) {
- instance = new MybatisFlexBootstrap();
+ instance = new MybatisFlexBootstrap(FlexConsts.NAME);
}
}
}
@@ -113,7 +114,7 @@ public class MybatisFlexBootstrap {
transactionFactory = new JdbcTransactionFactory();
}
- Environment environment = new Environment(environmentId, transactionFactory, dataSource);
+ Environment environment = new Environment(environmentId, transactionFactory, new RoutingDataSource(environmentId, dataSource));
configuration = new FlexConfiguration(environment);
}
@@ -142,11 +143,8 @@ public class MybatisFlexBootstrap {
@Deprecated
public R execute(Class mapperClass, Function function) {
try (SqlSession sqlSession = openSession()) {
- DialectFactory.setHintDbType(dbType);
T mapper = sqlSession.getMapper(mapperClass);
return function.apply(mapper);
- } finally {
- DialectFactory.clearHintDbType();
}
}
@@ -162,20 +160,18 @@ public class MybatisFlexBootstrap {
/**
* 直接获取 mapper 对象执行
+ *
* @param mapperClass
* @return mapperObject
*/
public T getMapper(Class mapperClass) {
Object mapperObject = MapUtil.computeIfAbsent(mapperObjects, mapperClass, clazz ->
- Proxy.newProxyInstance(MybatisFlexBootstrap.class.getClassLoader()
+ Proxy.newProxyInstance(mapperClass.getClassLoader()
, new Class[]{mapperClass}
, (proxy, method, args) -> {
try (SqlSession sqlSession = openSession()) {
- DialectFactory.setHintDbType(dbType);
T mapper1 = sqlSession.getMapper(mapperClass);
return method.invoke(mapper1, args);
- } finally {
- DialectFactory.clearHintDbType();
}
}));
return (T) mapperObject;
@@ -210,7 +206,6 @@ public class MybatisFlexBootstrap {
}
-
public String getEnvironmentId() {
return environmentId;
}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/AbstractDataSource.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/AbstractDataSource.java
new file mode 100644
index 00000000..6fcb3ac0
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/AbstractDataSource.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.core.datasource;
+
+
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+
+public abstract class AbstractDataSource implements DataSource {
+
+
+ /**
+ * Returns 0, indicating the default system timeout is to be used.
+ */
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return 0;
+ }
+
+ /**
+ * Setting a login timeout is not supported.
+ */
+ @Override
+ public void setLoginTimeout(int timeout) throws SQLException {
+ throw new UnsupportedOperationException("setLoginTimeout");
+ }
+
+ /**
+ * LogWriter methods are not supported.
+ */
+ @Override
+ public PrintWriter getLogWriter() {
+ throw new UnsupportedOperationException("getLogWriter");
+ }
+
+ /**
+ * LogWriter methods are not supported.
+ */
+ @Override
+ public void setLogWriter(PrintWriter pw) throws SQLException {
+ throw new UnsupportedOperationException("setLogWriter");
+ }
+
+
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T unwrap(Class iface) throws SQLException {
+ if (iface.isInstance(this)) {
+ return (T) this;
+ }
+ throw new SQLException("DataSource of type [" + getClass().getName() +
+ "] cannot be unwrapped as [" + iface.getName() + "]");
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ return iface.isInstance(this);
+ }
+
+
+
+ @Override
+ public Logger getParentLogger() {
+ return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+ }
+
+}
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
new file mode 100644
index 00000000..9c5bbefe
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/DataSourceKey.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.core.datasource;
+
+public class DataSourceKey {
+
+ private static ThreadLocal keyThreadLocal = new ThreadLocal<>();
+
+ public static void use(String environmentId){
+ keyThreadLocal.set(environmentId);
+ }
+
+ public static void clear(){
+ keyThreadLocal.remove();
+ }
+
+ public static String get(){
+ return keyThreadLocal.get();
+ }
+
+}
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
new file mode 100644
index 00000000..1e5d1d2b
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/datasource/RoutingDataSource.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.core.datasource;
+
+import com.mybatisflex.core.util.StringUtil;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RoutingDataSource extends AbstractDataSource {
+
+ private static Map dataSourceMap = new HashMap<>();
+
+ private DataSource delegate;
+
+ public RoutingDataSource(String environmentId, DataSource delegate) {
+ this.delegate = delegate;
+ dataSourceMap.put(environmentId, delegate);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ return getDataSource().getConnection();
+ }
+
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException {
+ return getDataSource().getConnection(username, password);
+ }
+
+ private DataSource getDataSource() {
+ DataSource dataSource = delegate;
+ if (dataSourceMap.size() > 1) {
+ String environmentId = DataSourceKey.get();
+ if (StringUtil.isNotBlank(environmentId)) {
+ dataSource = dataSourceMap.get(environmentId);
+ if (dataSource == null) {
+ throw new IllegalStateException("Cannot get target DataSource for environmentId [" + environmentId + "]");
+ }
+ }
+ }
+ return dataSource;
+ }
+
+ public DataSource getDelegate() {
+ return delegate;
+ }
+
+}
diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java
index 1ea6489e..a3f01593 100644
--- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/FlexConfiguration.java
@@ -38,7 +38,9 @@ import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.session.SqlSession;
+import java.lang.reflect.Proxy;
import java.util.Map;
public class FlexConfiguration extends Configuration {
@@ -237,6 +239,7 @@ public class FlexConfiguration extends Configuration {
.build();
}
+
private TableInfo getTableInfo(MappedStatement ms) {
String mapperClassName = ms.getId().substring(0, ms.getId().lastIndexOf("."));
try {
@@ -248,4 +251,12 @@ public class FlexConfiguration extends Configuration {
}
+ @Override
+ public T getMapper(Class type, SqlSession sqlSession) {
+ T mapper = super.getMapper(type, sqlSession);
+ return (T) Proxy.newProxyInstance(type.getClassLoader()
+ , new Class[]{type}
+ , new MapperInvocationHandler(mapper, this));
+
+ }
}
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 abe8ed60..46376b2d 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
@@ -31,6 +31,8 @@ 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 {
@@ -94,17 +96,14 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
*/
private DbType getDbType(Configuration configuration) {
DataSource dataSource = configuration.getEnvironment().getDataSource();
+
String jdbcUrl = getJdbcUrl(dataSource);
- if (StringUtil.isNotBlank(jdbcUrl)){
+
+ if (StringUtil.isNotBlank(jdbcUrl)) {
return DbTypeUtil.parseDbType(jdbcUrl);
}
- if ("org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy"
- .equals(dataSource.getClass().getName())){
- return DbType.H2;
- }
-
- return null;
+ throw new IllegalStateException("Cannot get dataSource jdbcUrl: " + dataSource.getClass().getName());
}
/**
@@ -125,6 +124,22 @@ public class FlexSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
//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
new file mode 100644
index 00000000..13a129d9
--- /dev/null
+++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/mybatis/MapperInvocationHandler.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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.dialect.DbType;
+import com.mybatisflex.core.dialect.DialectFactory;
+import com.mybatisflex.core.util.StringUtil;
+import org.apache.ibatis.session.Configuration;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class MapperInvocationHandler implements InvocationHandler {
+
+ private Object mapper;
+ private Configuration configuration;
+
+ public MapperInvocationHandler(Object mapper, Configuration configuration) {
+ this.mapper = mapper;
+ this.configuration = configuration;
+ }
+
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ boolean clearDsKey = false;
+ boolean clearDbType = false;
+ try {
+ //获取用户动态指定,由用户指定数据源,则应该有用户清除
+ String environmentId = DataSourceKey.get();
+
+ //通过 方法 的注解去获取
+ if (StringUtil.isBlank(environmentId)) {
+ environmentId = getMethodEnvironmentId(method);
+ if (StringUtil.isNotBlank(environmentId)) {
+ DataSourceKey.use(environmentId);
+ clearDsKey = true;
+ }
+ }
+
+ if (StringUtil.isBlank(environmentId)) {
+ environmentId = configuration.getEnvironment().getId();
+ }
+
+ //优先获取用户自己配置的 dbType
+ DbType dbType = DialectFactory.getHintDbType();
+ if (dbType == null) {
+ dbType = FlexGlobalConfig.getConfig(environmentId).getDbType();
+ DialectFactory.setHintDbType(dbType);
+ clearDbType = true;
+ }
+ return method.invoke(mapper, args);
+ } finally {
+ if (clearDbType) {
+ DialectFactory.clearHintDbType();
+ }
+ if (clearDsKey) {
+ DataSourceKey.clear();
+ }
+ }
+ }
+
+
+ private String getMethodEnvironmentId(Method method) {
+ UseDataSource useDataSource = method.getAnnotation(UseDataSource.class);
+ return useDataSource != null ? useDataSource.value() : null;
+ }
+
+}
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 d5637ec9..d1e7c71c 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
@@ -17,7 +17,6 @@ package com.mybatisflex.core.row;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.DbType;
-import com.mybatisflex.core.dialect.DialectFactory;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.ibatis.executor.BatchResult;
@@ -52,11 +51,9 @@ public class RowMapperInvoker {
private R execute(Function function) {
SqlSession sqlSession = rowSessionManager.getSqlSession(sqlSessionFactory);
try {
- DialectFactory.setHintDbType(dbType);
RowMapper mapper = sqlSession.getMapper(RowMapper.class);
return function.apply(mapper);
} finally {
- DialectFactory.clearHintDbType();
rowSessionManager.releaseSqlSession(sqlSession, sqlSessionFactory);
}
}
@@ -75,7 +72,6 @@ public class RowMapperInvoker {
int[] results = new int[rows.size()];
SqlSession sqlSession = rowSessionManager.getSqlSession(sqlSessionFactory, ExecutorType.BATCH);
try {
- DialectFactory.setHintDbType(dbType);
RowMapper mapper = sqlSession.getMapper(RowMapper.class);
int counter = 0;
int resultsPos = 0;
@@ -94,7 +90,6 @@ public class RowMapperInvoker {
}
}
} finally {
- DialectFactory.clearHintDbType();
rowSessionManager.releaseSqlSession(sqlSession, sqlSessionFactory);
}
return results;
diff --git a/mybatis-flex-spring-boot-starter/pom.xml b/mybatis-flex-spring-boot-starter/pom.xml
index a64e1b8d..274d2e86 100644
--- a/mybatis-flex-spring-boot-starter/pom.xml
+++ b/mybatis-flex-spring-boot-starter/pom.xml
@@ -47,6 +47,39 @@
true
+
+ com.zaxxer
+ HikariCP
+ 4.0.3
+ compile
+ true
+
+
+
+ com.alibaba
+ druid
+ 1.2.16
+ compile
+ true
+
+
+
+ com.github.chris2018998
+ beecp
+ 3.4.0
+ compile
+ true
+
+
+
+ org.apache.commons
+ commons-dbcp2
+ 2.9.0
+ compile
+ true
+
+
+
diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/ConditionalOnPropertyEmpty.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/ConditionalOnPropertyEmpty.java
new file mode 100644
index 00000000..4f274e29
--- /dev/null
+++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/ConditionalOnPropertyEmpty.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.spring.boot;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Map;
+
+
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Conditional(ConditionalOnPropertyEmpty.OnPropertyNotEmptyCondition.class)
+public @interface ConditionalOnPropertyEmpty {
+
+ String value();
+
+ class OnPropertyNotEmptyCondition implements Condition {
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ Map attrs = metadata.getAnnotationAttributes(ConditionalOnPropertyEmpty.class.getName());
+ if (attrs == null) {
+ return false;
+ }
+ String propertyName = (String) attrs.get("value");
+ String val = context.getEnvironment().getProperty(propertyName);
+ return val == null || val.trim().length() == 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceProperty.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceProperty.java
new file mode 100644
index 00000000..bea74a3b
--- /dev/null
+++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/DataSourceProperty.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.spring.boot;
+
+/**
+ * 参考 {@link org.springframework.boot.autoconfigure.jdbc.DataSourceProperties}
+ * 自定义 DataSourceProperty,在未来可以提供更多的扩展
+ */
+public class DataSourceProperty {
+
+ private String type;
+ private String driverClassName;
+ private String url;
+ private String username;
+ private String password;
+
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getDriverClassName() {
+ return driverClassName;
+ }
+
+ public void setDriverClassName(String driverClassName) {
+ this.driverClassName = driverClassName;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
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
new file mode 100644
index 00000000..6b6c291b
--- /dev/null
+++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MultiDataSourceAutoConfiguration.java
@@ -0,0 +1,278 @@
+/**
+ * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.mybatisflex.spring.boot;
+
+import cn.beecp.BeeDataSource;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.mybatisflex.core.datasource.RoutingDataSource;
+import com.mybatisflex.core.util.StringUtil;
+import com.mybatisflex.spring.FlexSqlSessionFactoryBean;
+import com.zaxxer.hikari.HikariDataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+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.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+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.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+
+/**
+ * 多数据源的配置支持
+ */
+@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
+@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
+@ConditionalOnPropertyEmpty("spring.datasource.url")
+@EnableConfigurationProperties(MybatisFlexProperties.class)
+@AutoConfigureAfter({MybatisLanguageDriverAutoConfiguration.class})
+public class MultiDataSourceAutoConfiguration extends MybatisFlexAutoConfiguration {
+
+ private List sqlSessionFactories = new ArrayList<>();
+ private List dataSources = new ArrayList<>();
+
+
+ private static Map dataSourceAlias = new HashMap<>();
+
+ static {
+ dataSourceAlias.put("druid", "com.alibaba.druid.pool.DruidDataSource");
+ dataSourceAlias.put("hikari", "com.zaxxer.hikari.HikariDataSource");
+ dataSourceAlias.put("hikaricp", "com.zaxxer.hikari.HikariDataSource");
+ dataSourceAlias.put("bee", "cn.beecp.BeeDataSource");
+ dataSourceAlias.put("beecp", "cn.beecp.BeeDataSource");
+ dataSourceAlias.put("dbcp", "org.apache.commons.dbcp2.BasicDataSource");
+ dataSourceAlias.put("dbcp2", "org.apache.commons.dbcp2.BasicDataSource");
+ }
+
+
+ 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) {
+ datasourceMap.forEach((s, dsp) -> {
+ SqlSessionFactory sqlSessionFactory = buildSqlSessionFactory(s, createDataSource(dsp));
+ sqlSessionFactories.add(sqlSessionFactory);
+ });
+ }
+
+
+ private DataSource createDataSource(DataSourceProperty dataSourceProperty) {
+ String type = dataSourceProperty.getType();
+ if (StringUtil.isBlank(type)) {
+ type = detectDataSourceClass();
+ }
+ if (StringUtil.isBlank(type)) {
+ throw new IllegalArgumentException("The dataSource cannot be null or empty.");
+ }
+
+ switch (type) {
+ case "druid":
+ case "com.alibaba.druid.pool.DruidDataSource":
+ return createDruidDataSource(dataSourceProperty);
+ case "hikari":
+ case "hikaricp":
+ case "com.zaxxer.hikari.HikariDataSource":
+ return createHikariDataSource(dataSourceProperty);
+ case "bee":
+ case "beecp":
+ case "cn.beecp.BeeDataSource":
+ return createBeeDataSource(dataSourceProperty);
+ case "dbcp":
+ case "dbcp2":
+ case "org.apache.commons.dbcp2.BasicDataSource":
+ return createDbcpDataSource(dataSourceProperty);
+ default:
+ throw new IllegalArgumentException("Cannot Support the dataSource type:" + dataSourceProperty.getType());
+ }
+ }
+
+
+ private String detectDataSourceClass() {
+ String[] detectClassNames = new String[]{
+ "com.alibaba.druid.pool.DruidDataSource",
+ "com.zaxxer.hikari.HikariDataSource",
+ "cn.beecp.BeeDataSource",
+ "org.apache.commons.dbcp2.BasicDataSource",
+ };
+
+ for (String detectClassName : detectClassNames) {
+ String result = doDetectDataSourceClass(detectClassName);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ return null;
+ }
+
+ private String doDetectDataSourceClass(String className) {
+ try {
+ Class.forName(className);
+ return className;
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ private DataSource createDbcpDataSource(DataSourceProperty dataSourceProperty) {
+ BasicDataSource ds = new BasicDataSource();
+ ds.setUrl(dataSourceProperty.getUrl());
+ ds.setUsername(dataSourceProperty.getUsername());
+ ds.setPassword(dataSourceProperty.getPassword());
+ ds.setDriverClassName(dataSourceProperty.getDriverClassName());
+ return ds;
+ }
+
+ private DataSource createBeeDataSource(DataSourceProperty dataSourceProperty) {
+ BeeDataSource ds = new BeeDataSource();
+ ds.setJdbcUrl(dataSourceProperty.getUrl());
+ ds.setUsername(dataSourceProperty.getUsername());
+ ds.setPassword(dataSourceProperty.getPassword());
+ ds.setDriverClassName(dataSourceProperty.getDriverClassName());
+ return ds;
+ }
+
+
+ private DataSource createDruidDataSource(DataSourceProperty dataSourceProperty) {
+ DruidDataSource ds = new DruidDataSource();
+ ds.setUrl(dataSourceProperty.getUrl());
+ ds.setUsername(dataSourceProperty.getUsername());
+ ds.setPassword(dataSourceProperty.getPassword());
+ ds.setDriverClassName(dataSourceProperty.getDriverClassName());
+ return ds;
+ }
+
+
+ private DataSource createHikariDataSource(DataSourceProperty dataSourceProperty) {
+ HikariDataSource ds = new HikariDataSource();
+ ds.setJdbcUrl(dataSourceProperty.getUrl());
+ ds.setUsername(dataSourceProperty.getUsername());
+ ds.setPassword(dataSourceProperty.getPassword());
+ if (StringUtil.isNotBlank(dataSourceProperty.getDriverClassName())) {
+ ds.setDriverClassName(dataSourceProperty.getDriverClassName());
+ }
+ return ds;
+ }
+
+
+ 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 extends LanguageDriver> 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.get(0);
+ }
+
+
+ @Bean
+ @ConditionalOnMissingBean
+ public DataSource dataSource() {
+ return dataSources.get(0);
+ }
+
+
+}
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 407283a6..0e36bae8 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,8 +40,8 @@ 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;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
@@ -80,28 +80,30 @@ 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})
+//@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
+@AutoConfigureAfter({ MybatisLanguageDriverAutoConfiguration.class})
public class MybatisFlexAutoConfiguration implements InitializingBean {
- private static final Logger logger = LoggerFactory.getLogger(MybatisFlexAutoConfiguration.class);
+ protected static final Logger logger = LoggerFactory.getLogger(MybatisFlexAutoConfiguration.class);
- private final MybatisFlexProperties properties;
+ protected final MybatisFlexProperties properties;
- private final Interceptor[] interceptors;
+ protected final Interceptor[] interceptors;
- private final TypeHandler[] typeHandlers;
+ protected final TypeHandler[] typeHandlers;
- private final LanguageDriver[] languageDrivers;
+ protected final LanguageDriver[] languageDrivers;
- private final ResourceLoader resourceLoader;
+ protected final ResourceLoader resourceLoader;
- private final DatabaseIdProvider databaseIdProvider;
+ protected final DatabaseIdProvider databaseIdProvider;
- private final List configurationCustomizers;
+ protected final List configurationCustomizers;
- private final List sqlSessionFactoryBeanCustomizers;
+ protected final List sqlSessionFactoryBeanCustomizers;
public MybatisFlexAutoConfiguration(MybatisFlexProperties properties, ObjectProvider interceptorsProvider,
ObjectProvider typeHandlersProvider, ObjectProvider languageDriversProvider,
@@ -188,7 +190,7 @@ public class MybatisFlexAutoConfiguration implements InitializingBean {
return factory.getObject();
}
- private void applyConfiguration(SqlSessionFactoryBean factory) {
+ protected void applyConfiguration(SqlSessionFactoryBean factory) {
MybatisFlexProperties.CoreConfiguration coreConfiguration = this.properties.getConfiguration();
// Configuration configuration = null;
FlexConfiguration configuration = null;
@@ -206,7 +208,7 @@ public class MybatisFlexAutoConfiguration implements InitializingBean {
factory.setConfiguration(configuration);
}
- private void applySqlSessionFactoryBeanCustomizers(SqlSessionFactoryBean factory) {
+ protected void applySqlSessionFactoryBeanCustomizers(SqlSessionFactoryBean factory) {
if (!CollectionUtils.isEmpty(this.sqlSessionFactoryBeanCustomizers)) {
for (SqlSessionFactoryBeanCustomizer customizer : this.sqlSessionFactoryBeanCustomizers) {
customizer.customize(factory);
diff --git a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexProperties.java b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexProperties.java
index aab26d17..97cd24bd 100644
--- a/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexProperties.java
+++ b/mybatis-flex-spring-boot-starter/src/main/java/com/mybatisflex/spring/boot/MybatisFlexProperties.java
@@ -29,6 +29,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;
+import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
@@ -42,649 +43,662 @@ import java.util.stream.Stream;
public class MybatisFlexProperties {
- private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
+ private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
- /**
- * Location of MyBatis xml config file.
- */
- private String configLocation;
-
- /**
- * Locations of MyBatis mapper files.
- */
- private String[] mapperLocations;
-
- /**
- * Packages to search type aliases. (Package delimiters are ",; \t\n")
- */
- private String typeAliasesPackage;
-
- /**
- * The super class for filtering type alias. If this not specifies, the MyBatis deal as type alias all classes that
- * searched from typeAliasesPackage.
- */
- private Class> typeAliasesSuperType;
-
- /**
- * Packages to search for type handlers. (Package delimiters are ",; \t\n")
- */
- private String typeHandlersPackage;
-
- /**
- * Indicates whether perform presence check of the MyBatis xml config file.
- */
- private boolean checkConfigLocation = false;
-
- /**
- * Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}.
- */
- private ExecutorType executorType;
-
- /**
- * The default scripting language driver class. (Available when use together with mybatis-spring 2.0.2+)
- */
- private Class extends LanguageDriver> defaultScriptingLanguageDriver;
-
- /**
- * Externalized properties for MyBatis configuration.
- */
- private Properties configurationProperties;
-
- /**
- * A Configuration object for customize default settings. If {@link #configLocation} is specified, this property is
- * not used.
- */
- private CoreConfiguration configuration;
-
- /**
- * @since 1.1.0
- */
- public String getConfigLocation() {
- return this.configLocation;
- }
-
- /**
- * @since 1.1.0
- */
- public void setConfigLocation(String configLocation) {
- this.configLocation = configLocation;
- }
-
- public String[] getMapperLocations() {
- return this.mapperLocations;
- }
-
- public void setMapperLocations(String[] mapperLocations) {
- this.mapperLocations = mapperLocations;
- }
-
- public String getTypeHandlersPackage() {
- return this.typeHandlersPackage;
- }
-
- public void setTypeHandlersPackage(String typeHandlersPackage) {
- this.typeHandlersPackage = typeHandlersPackage;
- }
-
- public String getTypeAliasesPackage() {
- return this.typeAliasesPackage;
- }
-
- public void setTypeAliasesPackage(String typeAliasesPackage) {
- this.typeAliasesPackage = typeAliasesPackage;
- }
-
- /**
- * @since 1.3.3
- */
- public Class> getTypeAliasesSuperType() {
- return typeAliasesSuperType;
- }
-
- /**
- * @since 1.3.3
- */
- public void setTypeAliasesSuperType(Class> typeAliasesSuperType) {
- this.typeAliasesSuperType = typeAliasesSuperType;
- }
-
- public boolean isCheckConfigLocation() {
- return this.checkConfigLocation;
- }
-
- public void setCheckConfigLocation(boolean checkConfigLocation) {
- this.checkConfigLocation = checkConfigLocation;
- }
-
- public ExecutorType getExecutorType() {
- return this.executorType;
- }
-
- public void setExecutorType(ExecutorType executorType) {
- this.executorType = executorType;
- }
-
- /**
- * @since 2.1.0
- */
- public Class extends LanguageDriver> getDefaultScriptingLanguageDriver() {
- return defaultScriptingLanguageDriver;
- }
-
- /**
- * @since 2.1.0
- */
- public void setDefaultScriptingLanguageDriver(Class extends LanguageDriver> defaultScriptingLanguageDriver) {
- this.defaultScriptingLanguageDriver = defaultScriptingLanguageDriver;
- }
-
- /**
- * @since 1.2.0
- */
- public Properties getConfigurationProperties() {
- return configurationProperties;
- }
-
- /**
- * @since 1.2.0
- */
- public void setConfigurationProperties(Properties configurationProperties) {
- this.configurationProperties = configurationProperties;
- }
-
- public CoreConfiguration getConfiguration() {
- return configuration;
- }
-
- public void setConfiguration(CoreConfiguration configuration) {
- this.configuration = configuration;
- }
-
- public Resource[] resolveMapperLocations() {
- return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0]))
- .flatMap(location -> Stream.of(getResources(location))).toArray(Resource[]::new);
- }
-
- private Resource[] getResources(String location) {
- try {
- return resourceResolver.getResources(location);
- } catch (IOException e) {
- return new Resource[0];
- }
- }
-
- /**
- * The configuration properties for mybatis core module.
- *
- * @since 3.0.0
- */
- public static class CoreConfiguration {
+ //多数据源的配置
+ //mybatis-flex.datasource.ds1.url=***
+ //mybatis-flex.datasource.ds2.url=***
+ private Map datasource;
/**
- * Allows using RowBounds on nested statements. If allow, set the false. Default is false.
+ * Location of MyBatis xml config file.
*/
- private Boolean safeRowBoundsEnabled;
+ private String configLocation;
/**
- * Allows using ResultHandler on nested statements. If allow, set the false. Default is true.
+ * Locations of MyBatis mapper files.
*/
- private Boolean safeResultHandlerEnabled;
+ private String[] mapperLocations;
/**
- * Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names
- * aColumn. Default is true.
+ * Packages to search type aliases. (Package delimiters are ",; \t\n")
*/
- private Boolean mapUnderscoreToCamelCase = true;
+ private String typeAliasesPackage;
/**
- * When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded
- * on demand (see also lazyLoadTriggerMethods). Default is false.
+ * The super class for filtering type alias. If this not specifies, the MyBatis deal as type alias all classes that
+ * searched from typeAliasesPackage.
*/
- private Boolean aggressiveLazyLoading;
+ private Class> typeAliasesSuperType;
/**
- * Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required).
- * Default is true.
+ * Packages to search for type handlers. (Package delimiters are ",; \t\n")
*/
- private Boolean multipleResultSetsEnabled;
+ private String typeHandlersPackage;
/**
- * Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be
- * used if set to true, as some drivers deny compatibility but still work (e.g. Derby). Default is false.
+ * Indicates whether perform presence check of the MyBatis xml config file.
*/
- private Boolean useGeneratedKeys;
+ private boolean checkConfigLocation = false;
/**
- * Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to
- * the driver documentation, or test out both modes to determine how your driver behaves. Default is true.
+ * Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}.
*/
- private Boolean useColumnLabel;
+ private ExecutorType executorType;
/**
- * Globally enables or disables any caches configured in any mapper under this configuration. Default is true.
+ * The default scripting language driver class. (Available when use together with mybatis-spring 2.0.2+)
*/
- private Boolean cacheEnabled;
+ private Class extends LanguageDriver> defaultScriptingLanguageDriver;
/**
- * Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you
- * rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to
- * null. Default is false.
+ * Externalized properties for MyBatis configuration.
*/
- private Boolean callSettersOnNulls;
+ private Properties configurationProperties;
/**
- * Allow referencing statement parameters by their actual names declared in the method signature. To use this
- * feature, your project must be compiled in Java 8 with -parameters option. Default is true.
+ * A Configuration object for customize default settings. If {@link #configLocation} is specified, this property is
+ * not used.
*/
- private Boolean useActualParamName;
+ private CoreConfiguration configuration;
+
+ public Map getDatasource() {
+ return datasource;
+ }
+
+ public void setDatasource(Map datasource) {
+ this.datasource = datasource;
+ }
/**
- * MyBatis, by default, returns null when all the columns of a returned row are NULL. When this setting is enabled,
- * MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collectioin and
- * association). Default is false.
+ * @since 1.1.0
*/
- private Boolean returnInstanceForEmptyRow;
+ public String getConfigLocation() {
+ return this.configLocation;
+ }
/**
- * Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. Default is
- * false.
+ * @since 1.1.0
*/
- private Boolean shrinkWhitespacesInSql;
+ public void setConfigLocation(String configLocation) {
+ this.configLocation = configLocation;
+ }
+
+ public String[] getMapperLocations() {
+ return this.mapperLocations;
+ }
+
+ public void setMapperLocations(String[] mapperLocations) {
+ this.mapperLocations = mapperLocations;
+ }
+
+ public String getTypeHandlersPackage() {
+ return this.typeHandlersPackage;
+ }
+
+ public void setTypeHandlersPackage(String typeHandlersPackage) {
+ this.typeHandlersPackage = typeHandlersPackage;
+ }
+
+ public String getTypeAliasesPackage() {
+ return this.typeAliasesPackage;
+ }
+
+ public void setTypeAliasesPackage(String typeAliasesPackage) {
+ this.typeAliasesPackage = typeAliasesPackage;
+ }
/**
- * Specifies the default value of 'nullable' attribute on 'foreach' tag. Default is false.
+ * @since 1.3.3
*/
- private Boolean nullableOnForEach;
+ public Class> getTypeAliasesSuperType() {
+ return typeAliasesSuperType;
+ }
/**
- * When applying constructor auto-mapping, argument name is used to search the column to map instead of relying on
- * the column order. Default is false.
+ * @since 1.3.3
*/
- private Boolean argNameBasedConstructorAutoMapping;
+ public void setTypeAliasesSuperType(Class> typeAliasesSuperType) {
+ this.typeAliasesSuperType = typeAliasesSuperType;
+ }
+
+ public boolean isCheckConfigLocation() {
+ return this.checkConfigLocation;
+ }
+
+ public void setCheckConfigLocation(boolean checkConfigLocation) {
+ this.checkConfigLocation = checkConfigLocation;
+ }
+
+ public ExecutorType getExecutorType() {
+ return this.executorType;
+ }
+
+ public void setExecutorType(ExecutorType executorType) {
+ this.executorType = executorType;
+ }
/**
- * Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be
- * superseded for a specific relation by using the fetchType attribute on it. Default is False.
+ * @since 2.1.0
*/
- private Boolean lazyLoadingEnabled;
+ public Class extends LanguageDriver> getDefaultScriptingLanguageDriver() {
+ return defaultScriptingLanguageDriver;
+ }
/**
- * Sets the number of seconds the driver will wait for a response from the database.
+ * @since 2.1.0
*/
- private Integer defaultStatementTimeout;
+ public void setDefaultScriptingLanguageDriver(Class extends LanguageDriver> defaultScriptingLanguageDriver) {
+ this.defaultScriptingLanguageDriver = defaultScriptingLanguageDriver;
+ }
/**
- * Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a
- * query setting.
+ * @since 1.2.0
*/
- private Integer defaultFetchSize;
+ public Properties getConfigurationProperties() {
+ return configurationProperties;
+ }
/**
- * MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default
- * (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be
- * used just for statement execution, no data will be shared between two different calls to the same SqlSession.
- * Default is SESSION.
+ * @since 1.2.0
*/
- private LocalCacheScope localCacheScope;
+ public void setConfigurationProperties(Properties configurationProperties) {
+ this.configurationProperties = configurationProperties;
+ }
+
+ public CoreConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public void setConfiguration(CoreConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public Resource[] resolveMapperLocations() {
+ return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0]))
+ .flatMap(location -> Stream.of(getResources(location))).toArray(Resource[]::new);
+ }
+
+ private Resource[] getResources(String location) {
+ try {
+ return resourceResolver.getResources(location);
+ } catch (IOException e) {
+ return new Resource[0];
+ }
+ }
/**
- * Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers
- * require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. Default
- * is OTHER.
+ * The configuration properties for mybatis core module.
+ *
+ * @since 3.0.0
*/
- private JdbcType jdbcTypeForNull;
+ public static class CoreConfiguration {
- /**
- * Specifies a scroll strategy when omit it per statement settings.
- */
- private ResultSetType defaultResultSetType;
+ /**
+ * Allows using RowBounds on nested statements. If allow, set the false. Default is false.
+ */
+ private Boolean safeRowBoundsEnabled;
- /**
- * Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements.
- * BATCH executor reuses statements and batches updates. Default is SIMPLE.
- */
- private ExecutorType defaultExecutorType;
+ /**
+ * Allows using ResultHandler on nested statements. If allow, set the false. Default is true.
+ */
+ private Boolean safeResultHandlerEnabled;
- /**
- * Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping.
- * PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result
- * mappings of any complexity (containing nested or otherwise). Default is PARTIAL.
- */
- private AutoMappingBehavior autoMappingBehavior;
+ /**
+ * Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names
+ * aColumn. Default is true.
+ */
+ private Boolean mapUnderscoreToCamelCase = true;
- /**
- * Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.
- * Default is NONE.
- */
- private AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior;
+ /**
+ * When enabled, any method call will load all the lazy properties of the object. Otherwise, each property is loaded
+ * on demand (see also lazyLoadTriggerMethods). Default is false.
+ */
+ private Boolean aggressiveLazyLoading;
- /**
- * Specifies the prefix string that MyBatis will add to the logger names.
- */
- private String logPrefix;
+ /**
+ * Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required).
+ * Default is true.
+ */
+ private Boolean multipleResultSetsEnabled;
- /**
- * Specifies which Object's methods trigger a lazy load. Default is [equals,clone,hashCode,toString].
- */
- private Set lazyLoadTriggerMethods;
+ /**
+ * Allows JDBC support for generated keys. A compatible driver is required. This setting forces generated keys to be
+ * used if set to true, as some drivers deny compatibility but still work (e.g. Derby). Default is false.
+ */
+ private Boolean useGeneratedKeys;
- /**
- * Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation
- * will be autodiscovered.
- */
- private Class extends Log> logImpl;
+ /**
+ * Uses the column label instead of the column name. Different drivers behave differently in this respect. Refer to
+ * the driver documentation, or test out both modes to determine how your driver behaves. Default is true.
+ */
+ private Boolean useColumnLabel;
- /**
- * Specifies VFS implementations.
- */
- private Class extends VFS> vfsImpl;
+ /**
+ * Globally enables or disables any caches configured in any mapper under this configuration. Default is true.
+ */
+ private Boolean cacheEnabled;
- /**
- * Specifies an sql provider class that holds provider method. This class apply to the type(or value) attribute on
- * sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.
- */
- private Class> defaultSqlProviderType;
+ /**
+ * Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you
+ * rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to
+ * null. Default is false.
+ */
+ private Boolean callSettersOnNulls;
- /**
- * Specifies the TypeHandler used by default for Enum.
- */
- Class extends TypeHandler> defaultEnumTypeHandler;
+ /**
+ * Allow referencing statement parameters by their actual names declared in the method signature. To use this
+ * feature, your project must be compiled in Java 8 with -parameters option. Default is true.
+ */
+ private Boolean useActualParamName;
- /**
- * Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to
- * load lazy properties of deserialized objects. This class must have a method with a signature static Configuration
- * getConfiguration().
- */
- private Class> configurationFactory;
+ /**
+ * MyBatis, by default, returns null when all the columns of a returned row are NULL. When this setting is enabled,
+ * MyBatis returns an empty instance instead. Note that it is also applied to nested results (i.e. collectioin and
+ * association). Default is false.
+ */
+ private Boolean returnInstanceForEmptyRow;
- /**
- * Specify any configuration variables.
- */
- private Properties variables;
+ /**
+ * Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. Default is
+ * false.
+ */
+ private Boolean shrinkWhitespacesInSql;
+
+ /**
+ * Specifies the default value of 'nullable' attribute on 'foreach' tag. Default is false.
+ */
+ private Boolean nullableOnForEach;
+
+ /**
+ * When applying constructor auto-mapping, argument name is used to search the column to map instead of relying on
+ * the column order. Default is false.
+ */
+ private Boolean argNameBasedConstructorAutoMapping;
+
+ /**
+ * Globally enables or disables lazy loading. When enabled, all relations will be lazily loaded. This value can be
+ * superseded for a specific relation by using the fetchType attribute on it. Default is False.
+ */
+ private Boolean lazyLoadingEnabled;
+
+ /**
+ * Sets the number of seconds the driver will wait for a response from the database.
+ */
+ private Integer defaultStatementTimeout;
+
+ /**
+ * Sets the driver a hint as to control fetching size for return results. This parameter value can be override by a
+ * query setting.
+ */
+ private Integer defaultFetchSize;
+
+ /**
+ * MyBatis uses local cache to prevent circular references and speed up repeated nested queries. By default
+ * (SESSION) all queries executed during a session are cached. If localCacheScope=STATEMENT local session will be
+ * used just for statement execution, no data will be shared between two different calls to the same SqlSession.
+ * Default is SESSION.
+ */
+ private LocalCacheScope localCacheScope;
+
+ /**
+ * Specifies the JDBC type for null values when no specific JDBC type was provided for the parameter. Some drivers
+ * require specifying the column JDBC type but others work with generic values like NULL, VARCHAR or OTHER. Default
+ * is OTHER.
+ */
+ private JdbcType jdbcTypeForNull;
+
+ /**
+ * Specifies a scroll strategy when omit it per statement settings.
+ */
+ private ResultSetType defaultResultSetType;
+
+ /**
+ * Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements.
+ * BATCH executor reuses statements and batches updates. Default is SIMPLE.
+ */
+ private ExecutorType defaultExecutorType;
+
+ /**
+ * Specifies if and how MyBatis should automatically map columns to fields/properties. NONE disables auto-mapping.
+ * PARTIAL will only auto-map results with no nested result mappings defined inside. FULL will auto-map result
+ * mappings of any complexity (containing nested or otherwise). Default is PARTIAL.
+ */
+ private AutoMappingBehavior autoMappingBehavior;
+
+ /**
+ * Specify the behavior when detects an unknown column (or unknown property type) of automatic mapping target.
+ * Default is NONE.
+ */
+ private AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior;
+
+ /**
+ * Specifies the prefix string that MyBatis will add to the logger names.
+ */
+ private String logPrefix;
+
+ /**
+ * Specifies which Object's methods trigger a lazy load. Default is [equals,clone,hashCode,toString].
+ */
+ private Set lazyLoadTriggerMethods;
+
+ /**
+ * Specifies which logging implementation MyBatis should use. If this setting is not present logging implementation
+ * will be autodiscovered.
+ */
+ private Class extends Log> logImpl;
+
+ /**
+ * Specifies VFS implementations.
+ */
+ private Class extends VFS> vfsImpl;
+
+ /**
+ * Specifies an sql provider class that holds provider method. This class apply to the type(or value) attribute on
+ * sql provider annotation(e.g. @SelectProvider), when these attribute was omitted.
+ */
+ private Class> defaultSqlProviderType;
+
+ /**
+ * Specifies the TypeHandler used by default for Enum.
+ */
+ Class extends TypeHandler> defaultEnumTypeHandler;
+
+ /**
+ * Specifies the class that provides an instance of Configuration. The returned Configuration instance is used to
+ * load lazy properties of deserialized objects. This class must have a method with a signature static Configuration
+ * getConfiguration().
+ */
+ private Class> configurationFactory;
+
+ /**
+ * Specify any configuration variables.
+ */
+ private Properties variables;
+
+ public Boolean getSafeRowBoundsEnabled() {
+ return safeRowBoundsEnabled;
+ }
+
+ public void setSafeRowBoundsEnabled(Boolean safeRowBoundsEnabled) {
+ this.safeRowBoundsEnabled = safeRowBoundsEnabled;
+ }
+
+ public Boolean getSafeResultHandlerEnabled() {
+ return safeResultHandlerEnabled;
+ }
+
+ public void setSafeResultHandlerEnabled(Boolean safeResultHandlerEnabled) {
+ this.safeResultHandlerEnabled = safeResultHandlerEnabled;
+ }
+
+ public Boolean getMapUnderscoreToCamelCase() {
+ return mapUnderscoreToCamelCase;
+ }
+
+ public void setMapUnderscoreToCamelCase(Boolean mapUnderscoreToCamelCase) {
+ this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
+ }
+
+ public Boolean getAggressiveLazyLoading() {
+ return aggressiveLazyLoading;
+ }
+
+ public void setAggressiveLazyLoading(Boolean aggressiveLazyLoading) {
+ this.aggressiveLazyLoading = aggressiveLazyLoading;
+ }
+
+ public Boolean getMultipleResultSetsEnabled() {
+ return multipleResultSetsEnabled;
+ }
+
+ public void setMultipleResultSetsEnabled(Boolean multipleResultSetsEnabled) {
+ this.multipleResultSetsEnabled = multipleResultSetsEnabled;
+ }
+
+ public Boolean getUseGeneratedKeys() {
+ return useGeneratedKeys;
+ }
+
+ public void setUseGeneratedKeys(Boolean useGeneratedKeys) {
+ this.useGeneratedKeys = useGeneratedKeys;
+ }
+
+ public Boolean getUseColumnLabel() {
+ return useColumnLabel;
+ }
+
+ public void setUseColumnLabel(Boolean useColumnLabel) {
+ this.useColumnLabel = useColumnLabel;
+ }
+
+ public Boolean getCacheEnabled() {
+ return cacheEnabled;
+ }
+
+ public void setCacheEnabled(Boolean cacheEnabled) {
+ this.cacheEnabled = cacheEnabled;
+ }
+
+ public Boolean getCallSettersOnNulls() {
+ return callSettersOnNulls;
+ }
+
+ public void setCallSettersOnNulls(Boolean callSettersOnNulls) {
+ this.callSettersOnNulls = callSettersOnNulls;
+ }
+
+ public Boolean getUseActualParamName() {
+ return useActualParamName;
+ }
+
+ public void setUseActualParamName(Boolean useActualParamName) {
+ this.useActualParamName = useActualParamName;
+ }
+
+ public Boolean getReturnInstanceForEmptyRow() {
+ return returnInstanceForEmptyRow;
+ }
+
+ public void setReturnInstanceForEmptyRow(Boolean returnInstanceForEmptyRow) {
+ this.returnInstanceForEmptyRow = returnInstanceForEmptyRow;
+ }
+
+ public Boolean getShrinkWhitespacesInSql() {
+ return shrinkWhitespacesInSql;
+ }
+
+ public void setShrinkWhitespacesInSql(Boolean shrinkWhitespacesInSql) {
+ this.shrinkWhitespacesInSql = shrinkWhitespacesInSql;
+ }
+
+ public Boolean getNullableOnForEach() {
+ return nullableOnForEach;
+ }
+
+ public void setNullableOnForEach(Boolean nullableOnForEach) {
+ this.nullableOnForEach = nullableOnForEach;
+ }
+
+ public Boolean getArgNameBasedConstructorAutoMapping() {
+ return argNameBasedConstructorAutoMapping;
+ }
+
+ public void setArgNameBasedConstructorAutoMapping(Boolean argNameBasedConstructorAutoMapping) {
+ this.argNameBasedConstructorAutoMapping = argNameBasedConstructorAutoMapping;
+ }
+
+ public String getLogPrefix() {
+ return logPrefix;
+ }
+
+ public void setLogPrefix(String logPrefix) {
+ this.logPrefix = logPrefix;
+ }
+
+ public Class extends Log> getLogImpl() {
+ return logImpl;
+ }
+
+ public void setLogImpl(Class extends Log> logImpl) {
+ this.logImpl = logImpl;
+ }
+
+ public Class extends VFS> getVfsImpl() {
+ return vfsImpl;
+ }
+
+ public void setVfsImpl(Class extends VFS> vfsImpl) {
+ this.vfsImpl = vfsImpl;
+ }
+
+ public Class> getDefaultSqlProviderType() {
+ return defaultSqlProviderType;
+ }
+
+ public void setDefaultSqlProviderType(Class> defaultSqlProviderType) {
+ this.defaultSqlProviderType = defaultSqlProviderType;
+ }
+
+ public LocalCacheScope getLocalCacheScope() {
+ return localCacheScope;
+ }
+
+ public void setLocalCacheScope(LocalCacheScope localCacheScope) {
+ this.localCacheScope = localCacheScope;
+ }
+
+ public JdbcType getJdbcTypeForNull() {
+ return jdbcTypeForNull;
+ }
+
+ public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) {
+ this.jdbcTypeForNull = jdbcTypeForNull;
+ }
+
+ public Set getLazyLoadTriggerMethods() {
+ return lazyLoadTriggerMethods;
+ }
+
+ public void setLazyLoadTriggerMethods(Set lazyLoadTriggerMethods) {
+ this.lazyLoadTriggerMethods = lazyLoadTriggerMethods;
+ }
+
+ public Integer getDefaultStatementTimeout() {
+ return defaultStatementTimeout;
+ }
+
+ public void setDefaultStatementTimeout(Integer defaultStatementTimeout) {
+ this.defaultStatementTimeout = defaultStatementTimeout;
+ }
+
+ public Integer getDefaultFetchSize() {
+ return defaultFetchSize;
+ }
+
+ public void setDefaultFetchSize(Integer defaultFetchSize) {
+ this.defaultFetchSize = defaultFetchSize;
+ }
+
+ public ResultSetType getDefaultResultSetType() {
+ return defaultResultSetType;
+ }
+
+ public void setDefaultResultSetType(ResultSetType defaultResultSetType) {
+ this.defaultResultSetType = defaultResultSetType;
+ }
+
+ public ExecutorType getDefaultExecutorType() {
+ return defaultExecutorType;
+ }
+
+ public void setDefaultExecutorType(ExecutorType defaultExecutorType) {
+ this.defaultExecutorType = defaultExecutorType;
+ }
+
+ public AutoMappingBehavior getAutoMappingBehavior() {
+ return autoMappingBehavior;
+ }
+
+ public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
+ this.autoMappingBehavior = autoMappingBehavior;
+ }
+
+ public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() {
+ return autoMappingUnknownColumnBehavior;
+ }
+
+ public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) {
+ this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior;
+ }
+
+ public Properties getVariables() {
+ return variables;
+ }
+
+ public void setVariables(Properties variables) {
+ this.variables = variables;
+ }
+
+ public Boolean getLazyLoadingEnabled() {
+ return lazyLoadingEnabled;
+ }
+
+ public void setLazyLoadingEnabled(Boolean lazyLoadingEnabled) {
+ this.lazyLoadingEnabled = lazyLoadingEnabled;
+ }
+
+ public Class> getConfigurationFactory() {
+ return configurationFactory;
+ }
+
+ public void setConfigurationFactory(Class> configurationFactory) {
+ this.configurationFactory = configurationFactory;
+ }
+
+ public Class extends TypeHandler> getDefaultEnumTypeHandler() {
+ return defaultEnumTypeHandler;
+ }
+
+ public void setDefaultEnumTypeHandler(Class extends TypeHandler> defaultEnumTypeHandler) {
+ this.defaultEnumTypeHandler = defaultEnumTypeHandler;
+ }
+
+ void applyTo(Configuration target) {
+ PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
+ mapper.from(getSafeRowBoundsEnabled()).to(target::setSafeRowBoundsEnabled);
+ mapper.from(getSafeResultHandlerEnabled()).to(target::setSafeResultHandlerEnabled);
+ mapper.from(getMapUnderscoreToCamelCase()).to(target::setMapUnderscoreToCamelCase);
+ mapper.from(getAggressiveLazyLoading()).to(target::setAggressiveLazyLoading);
+ mapper.from(getMultipleResultSetsEnabled()).to(target::setMultipleResultSetsEnabled);
+ mapper.from(getUseGeneratedKeys()).to(target::setUseGeneratedKeys);
+ mapper.from(getUseColumnLabel()).to(target::setUseColumnLabel);
+ mapper.from(getCacheEnabled()).to(target::setCacheEnabled);
+ mapper.from(getCallSettersOnNulls()).to(target::setCallSettersOnNulls);
+ mapper.from(getUseActualParamName()).to(target::setUseActualParamName);
+ mapper.from(getReturnInstanceForEmptyRow()).to(target::setReturnInstanceForEmptyRow);
+ mapper.from(getShrinkWhitespacesInSql()).to(target::setShrinkWhitespacesInSql);
+ mapper.from(getNullableOnForEach()).to(target::setNullableOnForEach);
+ mapper.from(getArgNameBasedConstructorAutoMapping()).to(target::setArgNameBasedConstructorAutoMapping);
+ mapper.from(getLazyLoadingEnabled()).to(target::setLazyLoadingEnabled);
+ mapper.from(getLogPrefix()).to(target::setLogPrefix);
+ mapper.from(getLazyLoadTriggerMethods()).to(target::setLazyLoadTriggerMethods);
+ mapper.from(getDefaultStatementTimeout()).to(target::setDefaultStatementTimeout);
+ mapper.from(getDefaultFetchSize()).to(target::setDefaultFetchSize);
+ mapper.from(getLocalCacheScope()).to(target::setLocalCacheScope);
+ mapper.from(getJdbcTypeForNull()).to(target::setJdbcTypeForNull);
+ mapper.from(getDefaultResultSetType()).to(target::setDefaultResultSetType);
+ mapper.from(getDefaultExecutorType()).to(target::setDefaultExecutorType);
+ mapper.from(getAutoMappingBehavior()).to(target::setAutoMappingBehavior);
+ mapper.from(getAutoMappingUnknownColumnBehavior()).to(target::setAutoMappingUnknownColumnBehavior);
+ mapper.from(getVariables()).to(target::setVariables);
+ mapper.from(getLogImpl()).to(target::setLogImpl);
+ mapper.from(getVfsImpl()).to(target::setVfsImpl);
+ mapper.from(getDefaultSqlProviderType()).to(target::setDefaultSqlProviderType);
+ mapper.from(getConfigurationFactory()).to(target::setConfigurationFactory);
+ mapper.from(getDefaultEnumTypeHandler()).to(target::setDefaultEnumTypeHandler);
+ }
- public Boolean getSafeRowBoundsEnabled() {
- return safeRowBoundsEnabled;
}
- public void setSafeRowBoundsEnabled(Boolean safeRowBoundsEnabled) {
- this.safeRowBoundsEnabled = safeRowBoundsEnabled;
- }
-
- public Boolean getSafeResultHandlerEnabled() {
- return safeResultHandlerEnabled;
- }
-
- public void setSafeResultHandlerEnabled(Boolean safeResultHandlerEnabled) {
- this.safeResultHandlerEnabled = safeResultHandlerEnabled;
- }
-
- public Boolean getMapUnderscoreToCamelCase() {
- return mapUnderscoreToCamelCase;
- }
-
- public void setMapUnderscoreToCamelCase(Boolean mapUnderscoreToCamelCase) {
- this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase;
- }
-
- public Boolean getAggressiveLazyLoading() {
- return aggressiveLazyLoading;
- }
-
- public void setAggressiveLazyLoading(Boolean aggressiveLazyLoading) {
- this.aggressiveLazyLoading = aggressiveLazyLoading;
- }
-
- public Boolean getMultipleResultSetsEnabled() {
- return multipleResultSetsEnabled;
- }
-
- public void setMultipleResultSetsEnabled(Boolean multipleResultSetsEnabled) {
- this.multipleResultSetsEnabled = multipleResultSetsEnabled;
- }
-
- public Boolean getUseGeneratedKeys() {
- return useGeneratedKeys;
- }
-
- public void setUseGeneratedKeys(Boolean useGeneratedKeys) {
- this.useGeneratedKeys = useGeneratedKeys;
- }
-
- public Boolean getUseColumnLabel() {
- return useColumnLabel;
- }
-
- public void setUseColumnLabel(Boolean useColumnLabel) {
- this.useColumnLabel = useColumnLabel;
- }
-
- public Boolean getCacheEnabled() {
- return cacheEnabled;
- }
-
- public void setCacheEnabled(Boolean cacheEnabled) {
- this.cacheEnabled = cacheEnabled;
- }
-
- public Boolean getCallSettersOnNulls() {
- return callSettersOnNulls;
- }
-
- public void setCallSettersOnNulls(Boolean callSettersOnNulls) {
- this.callSettersOnNulls = callSettersOnNulls;
- }
-
- public Boolean getUseActualParamName() {
- return useActualParamName;
- }
-
- public void setUseActualParamName(Boolean useActualParamName) {
- this.useActualParamName = useActualParamName;
- }
-
- public Boolean getReturnInstanceForEmptyRow() {
- return returnInstanceForEmptyRow;
- }
-
- public void setReturnInstanceForEmptyRow(Boolean returnInstanceForEmptyRow) {
- this.returnInstanceForEmptyRow = returnInstanceForEmptyRow;
- }
-
- public Boolean getShrinkWhitespacesInSql() {
- return shrinkWhitespacesInSql;
- }
-
- public void setShrinkWhitespacesInSql(Boolean shrinkWhitespacesInSql) {
- this.shrinkWhitespacesInSql = shrinkWhitespacesInSql;
- }
-
- public Boolean getNullableOnForEach() {
- return nullableOnForEach;
- }
-
- public void setNullableOnForEach(Boolean nullableOnForEach) {
- this.nullableOnForEach = nullableOnForEach;
- }
-
- public Boolean getArgNameBasedConstructorAutoMapping() {
- return argNameBasedConstructorAutoMapping;
- }
-
- public void setArgNameBasedConstructorAutoMapping(Boolean argNameBasedConstructorAutoMapping) {
- this.argNameBasedConstructorAutoMapping = argNameBasedConstructorAutoMapping;
- }
-
- public String getLogPrefix() {
- return logPrefix;
- }
-
- public void setLogPrefix(String logPrefix) {
- this.logPrefix = logPrefix;
- }
-
- public Class extends Log> getLogImpl() {
- return logImpl;
- }
-
- public void setLogImpl(Class extends Log> logImpl) {
- this.logImpl = logImpl;
- }
-
- public Class extends VFS> getVfsImpl() {
- return vfsImpl;
- }
-
- public void setVfsImpl(Class extends VFS> vfsImpl) {
- this.vfsImpl = vfsImpl;
- }
-
- public Class> getDefaultSqlProviderType() {
- return defaultSqlProviderType;
- }
-
- public void setDefaultSqlProviderType(Class> defaultSqlProviderType) {
- this.defaultSqlProviderType = defaultSqlProviderType;
- }
-
- public LocalCacheScope getLocalCacheScope() {
- return localCacheScope;
- }
-
- public void setLocalCacheScope(LocalCacheScope localCacheScope) {
- this.localCacheScope = localCacheScope;
- }
-
- public JdbcType getJdbcTypeForNull() {
- return jdbcTypeForNull;
- }
-
- public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) {
- this.jdbcTypeForNull = jdbcTypeForNull;
- }
-
- public Set getLazyLoadTriggerMethods() {
- return lazyLoadTriggerMethods;
- }
-
- public void setLazyLoadTriggerMethods(Set lazyLoadTriggerMethods) {
- this.lazyLoadTriggerMethods = lazyLoadTriggerMethods;
- }
-
- public Integer getDefaultStatementTimeout() {
- return defaultStatementTimeout;
- }
-
- public void setDefaultStatementTimeout(Integer defaultStatementTimeout) {
- this.defaultStatementTimeout = defaultStatementTimeout;
- }
-
- public Integer getDefaultFetchSize() {
- return defaultFetchSize;
- }
-
- public void setDefaultFetchSize(Integer defaultFetchSize) {
- this.defaultFetchSize = defaultFetchSize;
- }
-
- public ResultSetType getDefaultResultSetType() {
- return defaultResultSetType;
- }
-
- public void setDefaultResultSetType(ResultSetType defaultResultSetType) {
- this.defaultResultSetType = defaultResultSetType;
- }
-
- public ExecutorType getDefaultExecutorType() {
- return defaultExecutorType;
- }
-
- public void setDefaultExecutorType(ExecutorType defaultExecutorType) {
- this.defaultExecutorType = defaultExecutorType;
- }
-
- public AutoMappingBehavior getAutoMappingBehavior() {
- return autoMappingBehavior;
- }
-
- public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) {
- this.autoMappingBehavior = autoMappingBehavior;
- }
-
- public AutoMappingUnknownColumnBehavior getAutoMappingUnknownColumnBehavior() {
- return autoMappingUnknownColumnBehavior;
- }
-
- public void setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior) {
- this.autoMappingUnknownColumnBehavior = autoMappingUnknownColumnBehavior;
- }
-
- public Properties getVariables() {
- return variables;
- }
-
- public void setVariables(Properties variables) {
- this.variables = variables;
- }
-
- public Boolean getLazyLoadingEnabled() {
- return lazyLoadingEnabled;
- }
-
- public void setLazyLoadingEnabled(Boolean lazyLoadingEnabled) {
- this.lazyLoadingEnabled = lazyLoadingEnabled;
- }
-
- public Class> getConfigurationFactory() {
- return configurationFactory;
- }
-
- public void setConfigurationFactory(Class> configurationFactory) {
- this.configurationFactory = configurationFactory;
- }
-
- public Class extends TypeHandler> getDefaultEnumTypeHandler() {
- return defaultEnumTypeHandler;
- }
-
- public void setDefaultEnumTypeHandler(Class extends TypeHandler> defaultEnumTypeHandler) {
- this.defaultEnumTypeHandler = defaultEnumTypeHandler;
- }
-
- void applyTo(Configuration target) {
- PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
- mapper.from(getSafeRowBoundsEnabled()).to(target::setSafeRowBoundsEnabled);
- mapper.from(getSafeResultHandlerEnabled()).to(target::setSafeResultHandlerEnabled);
- mapper.from(getMapUnderscoreToCamelCase()).to(target::setMapUnderscoreToCamelCase);
- mapper.from(getAggressiveLazyLoading()).to(target::setAggressiveLazyLoading);
- mapper.from(getMultipleResultSetsEnabled()).to(target::setMultipleResultSetsEnabled);
- mapper.from(getUseGeneratedKeys()).to(target::setUseGeneratedKeys);
- mapper.from(getUseColumnLabel()).to(target::setUseColumnLabel);
- mapper.from(getCacheEnabled()).to(target::setCacheEnabled);
- mapper.from(getCallSettersOnNulls()).to(target::setCallSettersOnNulls);
- mapper.from(getUseActualParamName()).to(target::setUseActualParamName);
- mapper.from(getReturnInstanceForEmptyRow()).to(target::setReturnInstanceForEmptyRow);
- mapper.from(getShrinkWhitespacesInSql()).to(target::setShrinkWhitespacesInSql);
- mapper.from(getNullableOnForEach()).to(target::setNullableOnForEach);
- mapper.from(getArgNameBasedConstructorAutoMapping()).to(target::setArgNameBasedConstructorAutoMapping);
- mapper.from(getLazyLoadingEnabled()).to(target::setLazyLoadingEnabled);
- mapper.from(getLogPrefix()).to(target::setLogPrefix);
- mapper.from(getLazyLoadTriggerMethods()).to(target::setLazyLoadTriggerMethods);
- mapper.from(getDefaultStatementTimeout()).to(target::setDefaultStatementTimeout);
- mapper.from(getDefaultFetchSize()).to(target::setDefaultFetchSize);
- mapper.from(getLocalCacheScope()).to(target::setLocalCacheScope);
- mapper.from(getJdbcTypeForNull()).to(target::setJdbcTypeForNull);
- mapper.from(getDefaultResultSetType()).to(target::setDefaultResultSetType);
- mapper.from(getDefaultExecutorType()).to(target::setDefaultExecutorType);
- mapper.from(getAutoMappingBehavior()).to(target::setAutoMappingBehavior);
- mapper.from(getAutoMappingUnknownColumnBehavior()).to(target::setAutoMappingUnknownColumnBehavior);
- mapper.from(getVariables()).to(target::setVariables);
- mapper.from(getLogImpl()).to(target::setLogImpl);
- mapper.from(getVfsImpl()).to(target::setVfsImpl);
- mapper.from(getDefaultSqlProviderType()).to(target::setDefaultSqlProviderType);
- mapper.from(getConfigurationFactory()).to(target::setConfigurationFactory);
- mapper.from(getDefaultEnumTypeHandler()).to(target::setDefaultEnumTypeHandler);
- }
-
- }
-
}
diff --git a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 52ee23f0..d47a01cb 100644
--- a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -25,6 +25,12 @@
"reason": "The 'userdirective' is deprecated since Velocity 2.x. This property defined for keeping backward compatibility with older velocity version.",
"replacement": "mybatis-flex.scripting-language-driver.velocity.velocity-settings.runtime.custom_directives"
}
+ },
+ {
+ "defaultValue": true,
+ "name": "mybatis-flex.datasource",
+ "description": "多数据源配置",
+ "type": "java.util.Map"
}
]
}
diff --git a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring.factories b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring.factories
index 397ff41a..b64771df 100644
--- a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -3,5 +3,6 @@ org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDete
com.mybatisflex.spring.boot.MybatisFlexDependsOnDatabaseInitializationDetector
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mybatisflex.spring.boot.DbAutoConfiguration,\
+ com.mybatisflex.spring.boot.MultiDataSourceAutoConfiguration,\
com.mybatisflex.spring.boot.MybatisFlexAutoConfiguration,\
com.mybatisflex.spring.boot.MybatisLanguageDriverAutoConfiguration
\ No newline at end of file
diff --git a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index e2dfb7d7..5d48c6ab 100644
--- a/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/mybatis-flex-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,2 +1,4 @@
+com.mybatisflex.spring.boot.DbAutoConfiguration
+com.mybatisflex.spring.boot.MultiDataSourceAutoConfiguration
com.mybatisflex.spring.boot.MybatisFlexAutoConfiguration
com.mybatisflex.spring.boot.MybatisLanguageDriverAutoConfiguration
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 cbddee20..cc183bcc 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
@@ -15,6 +15,8 @@
*/
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;
@@ -101,7 +103,8 @@ public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean
private SqlSessionFactory sqlSessionFactory;
// EnvironmentAware requires spring 3.1
- private String environment = SqlSessionFactoryBean.class.getSimpleName();
+// private String environment = SqlSessionFactoryBean.class.getSimpleName();
+ private String environment = FlexConsts.NAME;
private boolean failFast;
@@ -581,7 +584,7 @@ public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean
targetConfiguration.setEnvironment(new Environment(this.environment,
this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
- this.dataSource));
+ dataSource instanceof RoutingDataSource ? dataSource : new RoutingDataSource(environment, this.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 733cf98c..8abfe04a 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
@@ -31,7 +31,7 @@ public class EntityTestStarter {
.addScript("data.sql")
.build();
- MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
+ MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
.setLogImpl(StdOutImpl.class)
.addMapper(AccountMapper.class)
diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/RowTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/RowTestStarter.java
index 5a95a270..b0cae942 100644
--- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/RowTestStarter.java
+++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/RowTestStarter.java
@@ -35,7 +35,7 @@ public class RowTestStarter {
.addScript("data.sql")
.build();
- MybatisFlexBootstrap bootstrap = new MybatisFlexBootstrap()
+ MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
.setLogImpl(StdOutImpl.class)
.start();
diff --git a/pom.xml b/pom.xml
index 1ce0b741..73500a72 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
+
org.mybatis
mybatis