mybatis-flex-solon-plugin:添加 MybatisFlexProperties 类,做为配置属性名的依据,进一步强化与 spring 的配置统一性

This commit is contained in:
noear 2024-12-16 22:45:04 +08:00
parent 5a819749a9
commit 7c942cb3cc
4 changed files with 1042 additions and 59 deletions

View File

@ -0,0 +1,986 @@
/*
* Copyright (c) 2022-2024, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.solon;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.FlexGlobalConfig;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.*;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.noear.solon.core.util.ResourceUtil;
import java.net.URI;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Stream;
/**
* Mybatis-Flex 的配置属性
* 参考https://github.com/mybatis/spring-boot-starter/blob/master/mybatis-spring-boot-autoconfigure/src/main/java/org/mybatis/spring/boot/autoconfigure/MybatisProperties.java
*
* @author Eddú Meléndez
* @author Kazuki Shimizu
* @author micahel
* @author 王帅
*/
public class MybatisFlexProperties {
private String defaultDatasourceKey;
/**
* <p>多数据源的配置
*
* <p>
* mybatis-flex.datasource.ds1.url=***<br>
* mybatis-flex.datasource.ds2.url=***
*/
private Map<String, Map<String, String>> datasource;
/**
* 全局配置
*/
private GlobalConfig globalConfig;
/**
* MyBatis-Flex-Admin 配置
*/
private AdminConfig adminConfig;
/**
* Location of MyBatis xml config file.
*/
private String configLocation;
/**
* Locations of MyBatis mapper files.
*/
private String[] mapperLocations = new String[]{"classpath*:/mapper/**/*.xml"};
/**
* 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.solon.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;
/**
* A Configuration object for seata
*/
private SeataConfig seataConfig;
public SeataConfig getSeataConfig() {
return seataConfig;
}
public void setSeataConfig(SeataConfig seataConfig) {
this.seataConfig = seataConfig;
}
public Map<String, Map<String, String>> getDatasource() {
return datasource;
}
public void setDatasource(Map<String, Map<String, String>> datasource) {
this.datasource = datasource;
}
public GlobalConfig getGlobalConfig() {
return globalConfig;
}
public void setGlobalConfig(GlobalConfig globalConfig) {
this.globalConfig = globalConfig;
}
public AdminConfig getAdminConfig() {
return adminConfig;
}
public void setAdminConfig(AdminConfig adminConfig) {
this.adminConfig = adminConfig;
}
public String getDefaultDatasourceKey() {
return defaultDatasourceKey;
}
public void setDefaultDatasourceKey(String defaultDatasourceKey) {
this.defaultDatasourceKey = defaultDatasourceKey;
}
/**
* @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 URI[] resolveMapperLocations() {
return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0]))
.flatMap(location -> Stream.of(getResources(location))).toArray(URI[]::new);
}
private URI[] getResources(String location) {
return ResourceUtil.scanResources(location).stream().map(m -> URI.create(m)).toArray(URI[]::new);
}
/**
* The configuration properties for mybatis core module.
*
* @since 3.0.0
*/
public static class CoreConfiguration {
/**
* Allows using RowBounds on nested statements. If allow, set the false. Default is false.
*/
private Boolean safeRowBoundsEnabled;
/**
* Allows using ResultHandler on nested statements. If allow, set the false. Default is true.
*/
private Boolean safeResultHandlerEnabled;
/**
* 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;
/**
* 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;
/**
* Allows or disallows multiple ResultSets to be returned from a single statement (compatible driver required).
* Default is true.
*/
private Boolean multipleResultSetsEnabled;
/**
* 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;
/**
* 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;
/**
* Globally enables or disables any caches configured in any mapper under this configuration. Default is true.
*/
private Boolean cacheEnabled;
/**
* 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;
/**
* 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;
/**
* 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;
/**
* 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<String> 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<String> getLazyLoadTriggerMethods() {
return lazyLoadTriggerMethods;
}
public void setLazyLoadTriggerMethods(Set<String> 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;
}
public void applyTo(Configuration target) {
Optional.ofNullable(getSafeRowBoundsEnabled()).ifPresent(target::setSafeRowBoundsEnabled);
Optional.ofNullable(getSafeRowBoundsEnabled()).ifPresent(target::setSafeRowBoundsEnabled);
Optional.ofNullable(getSafeResultHandlerEnabled()).ifPresent(target::setSafeResultHandlerEnabled);
Optional.ofNullable(getMapUnderscoreToCamelCase()).ifPresent(target::setMapUnderscoreToCamelCase);
Optional.ofNullable(getAggressiveLazyLoading()).ifPresent(target::setAggressiveLazyLoading);
Optional.ofNullable(getMultipleResultSetsEnabled()).ifPresent(target::setMultipleResultSetsEnabled);
Optional.ofNullable(getUseGeneratedKeys()).ifPresent(target::setUseGeneratedKeys);
Optional.ofNullable(getUseColumnLabel()).ifPresent(target::setUseColumnLabel);
Optional.ofNullable(getCacheEnabled()).ifPresent(target::setCacheEnabled);
Optional.ofNullable(getCallSettersOnNulls()).ifPresent(target::setCallSettersOnNulls);
Optional.ofNullable(getUseActualParamName()).ifPresent(target::setUseActualParamName);
Optional.ofNullable(getReturnInstanceForEmptyRow()).ifPresent(target::setReturnInstanceForEmptyRow);
Optional.ofNullable(getShrinkWhitespacesInSql()).ifPresent(target::setShrinkWhitespacesInSql);
Optional.ofNullable(getNullableOnForEach()).ifPresent(target::setNullableOnForEach);
Optional.ofNullable(getArgNameBasedConstructorAutoMapping()).ifPresent(target::setArgNameBasedConstructorAutoMapping);
Optional.ofNullable(getLazyLoadingEnabled()).ifPresent(target::setLazyLoadingEnabled);
Optional.ofNullable(getLogPrefix()).ifPresent(target::setLogPrefix);
Optional.ofNullable(getLazyLoadTriggerMethods()).ifPresent(target::setLazyLoadTriggerMethods);
Optional.ofNullable(getDefaultStatementTimeout()).ifPresent(target::setDefaultStatementTimeout);
Optional.ofNullable(getDefaultFetchSize()).ifPresent(target::setDefaultFetchSize);
Optional.ofNullable(getLocalCacheScope()).ifPresent(target::setLocalCacheScope);
Optional.ofNullable(getJdbcTypeForNull()).ifPresent(target::setJdbcTypeForNull);
Optional.ofNullable(getDefaultResultSetType()).ifPresent(target::setDefaultResultSetType);
Optional.ofNullable(getDefaultExecutorType()).ifPresent(target::setDefaultExecutorType);
Optional.ofNullable(getAutoMappingBehavior()).ifPresent(target::setAutoMappingBehavior);
Optional.ofNullable(getAutoMappingUnknownColumnBehavior()).ifPresent(target::setAutoMappingUnknownColumnBehavior);
Optional.ofNullable(getVariables()).ifPresent(target::setVariables);
Optional.ofNullable(getLogImpl()).ifPresent(target::setLogImpl);
Optional.ofNullable(getVfsImpl()).ifPresent(target::setVfsImpl);
Optional.ofNullable(getDefaultSqlProviderType()).ifPresent(target::setDefaultSqlProviderType);
Optional.ofNullable(getConfigurationFactory()).ifPresent(target::setConfigurationFactory);
Optional.ofNullable(getDefaultEnumTypeHandler()).ifPresent(target::setDefaultEnumTypeHandler);
}
}
/**
* {@link FlexGlobalConfig} 配置
*
* @author 王帅
* @since 2023-06-21
*/
public static class GlobalConfig {
/**
* 启动是否打印 banner 版本号
*/
private boolean printBanner = true;
/**
* 全局的 ID 生成策略配置 @Id 未配置 或者 配置 KeyType None
* 使用当前全局配置
*/
private FlexGlobalConfig.KeyConfig keyConfig;
/**
* 逻辑删除数据存在标记值
*/
private Object normalValueOfLogicDelete = FlexConsts.LOGIC_DELETE_NORMAL;
/**
* 逻辑删除数据删除标记值
*/
private Object deletedValueOfLogicDelete = FlexConsts.LOGIC_DELETE_DELETED;
/**
* 默认的分页查询时的每页数据量
*/
private int defaultPageSize = 10;
/**
* 默认的 Relation 注解查询深度
*/
private int defaultRelationQueryDepth = 2;
/**
* 默认的逻辑删除字段
*/
private String logicDeleteColumn;
/**
* 默认的多租户字段
*/
private String tenantColumn;
/**
* 默认的乐观锁字段
*/
private String versionColumn;
public boolean isPrintBanner() {
return printBanner;
}
public void setPrintBanner(boolean printBanner) {
this.printBanner = printBanner;
}
public FlexGlobalConfig.KeyConfig getKeyConfig() {
return keyConfig;
}
public void setKeyConfig(FlexGlobalConfig.KeyConfig keyConfig) {
this.keyConfig = keyConfig;
}
public Object getNormalValueOfLogicDelete() {
return normalValueOfLogicDelete;
}
public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) {
this.normalValueOfLogicDelete = normalValueOfLogicDelete;
}
public Object getDeletedValueOfLogicDelete() {
return deletedValueOfLogicDelete;
}
public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) {
this.deletedValueOfLogicDelete = deletedValueOfLogicDelete;
}
public int getDefaultPageSize() {
return defaultPageSize;
}
public void setDefaultPageSize(int defaultPageSize) {
this.defaultPageSize = defaultPageSize;
}
public int getDefaultRelationQueryDepth() {
return defaultRelationQueryDepth;
}
public void setDefaultRelationQueryDepth(int defaultRelationQueryDepth) {
this.defaultRelationQueryDepth = defaultRelationQueryDepth;
}
public String getLogicDeleteColumn() {
return logicDeleteColumn;
}
public void setLogicDeleteColumn(String logicDeleteColumn) {
this.logicDeleteColumn = logicDeleteColumn;
}
public String getTenantColumn() {
return tenantColumn;
}
public void setTenantColumn(String tenantColumn) {
this.tenantColumn = tenantColumn;
}
public String getVersionColumn() {
return versionColumn;
}
public void setVersionColumn(String versionColumn) {
this.versionColumn = versionColumn;
}
public void applyTo(FlexGlobalConfig target) {
Optional.ofNullable(isPrintBanner()).ifPresent(target::setPrintBanner);
Optional.ofNullable(getKeyConfig()).ifPresent(target::setKeyConfig);
Optional.ofNullable(getNormalValueOfLogicDelete()).ifPresent(target::setNormalValueOfLogicDelete);
Optional.ofNullable(getDeletedValueOfLogicDelete()).ifPresent(target::setDeletedValueOfLogicDelete);
Optional.ofNullable(getDefaultPageSize()).ifPresent(target::setDefaultPageSize);
Optional.ofNullable(getDefaultRelationQueryDepth()).ifPresent(target::setDefaultRelationQueryDepth);
Optional.ofNullable(getLogicDeleteColumn()).ifPresent(target::setLogicDeleteColumn);
Optional.ofNullable(getVersionColumn()).ifPresent(target::setVersionColumn);
Optional.ofNullable(getTenantColumn()).ifPresent(target::setTenantColumn);
}
}
/**
* MyBatis Flex Admin 配置
*
* @author 王帅
* @since 2023-07-02
*/
public static class AdminConfig {
/**
* 启用服务
*/
private boolean enable;
/**
* 连接端点
*/
private String endpoint;
/**
* 秘密密钥
*/
private String secretKey;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
}
/**
* Seata 配置
*
* @author life
*/
public static class SeataConfig {
/**
* 是否开启
*/
private boolean enable = false;
/**
* 事务模式支持只支持XA或者AT
*/
private SeataMode seataMode = SeataMode.AT;
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public SeataMode getSeataMode() {
return seataMode;
}
public void setSeataMode(SeataMode seataMode) {
this.seataMode = seataMode;
}
}
/**
* @author life
*/
public enum SeataMode {
XA,
AT
}
}

View File

@ -20,6 +20,7 @@ import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder; import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
import com.mybatisflex.core.row.RowMapperInvoker; import com.mybatisflex.core.row.RowMapperInvoker;
import com.mybatisflex.solon.MybatisFlexProperties;
import com.mybatisflex.solon.mybtais.MybatisAdapterDefault; import com.mybatisflex.solon.mybtais.MybatisAdapterDefault;
import org.apache.ibatis.mapping.Environment; import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
@ -28,7 +29,6 @@ import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.Props; import org.noear.solon.core.Props;
import org.noear.solon.core.VarHolder; import org.noear.solon.core.VarHolder;
import org.noear.solon.core.event.EventBus; import org.noear.solon.core.event.EventBus;
import org.noear.solon.core.util.ClassUtil;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -43,18 +43,16 @@ public class MybatisAdapterFlex extends MybatisAdapterDefault {
private FlexGlobalConfig globalConfig; private FlexGlobalConfig globalConfig;
private RowMapperInvoker rowMapperInvoker; private RowMapperInvoker rowMapperInvoker;
private Class<?> typeAliasesBaseType; private Class<?> typeAliasesBaseType;
private MybatisFlexProperties flexProperties;
protected MybatisAdapterFlex(BeanWrap dsWrap) { protected MybatisAdapterFlex(BeanWrap dsWrap, Props flexProps, MybatisFlexProperties flexProperties) {
super(dsWrap); this.factoryBuilderPlus = new FlexSqlSessionFactoryBuilder();
this.flexProperties = flexProperties;
factoryBuilderPlus = new FlexSqlSessionFactoryBuilder(); //初始化开始
initAfter(dsWrap); initStart(dsWrap, flexProps);
}
protected MybatisAdapterFlex(BeanWrap dsWrap, Props dsProps) { //初始化之前
super(dsWrap, dsProps);
factoryBuilderPlus = new FlexSqlSessionFactoryBuilder();
initAfter(dsWrap); initAfter(dsWrap);
} }
@ -72,17 +70,14 @@ public class MybatisAdapterFlex extends MybatisAdapterDefault {
//for configuration section //for configuration section
config = new FlexConfiguration(environment); config = new FlexConfiguration(environment);
String typeAliasesBaseTypeStr = dsProps.get("typeAliasesSuperType"); if (Utils.isNotEmpty(flexProperties.getConfigurationProperties())) {
if (Utils.isNotEmpty(typeAliasesBaseTypeStr)) { Utils.injectProperties(config, flexProperties.getConfigurationProperties());
typeAliasesBaseType = ClassUtil.loadClass(typeAliasesBaseTypeStr);
} }
Props cfgProps = dsProps.getProp("configuration"); if (flexProperties.getConfiguration() != null) {
if (cfgProps.size() > 0) { flexProperties.getConfiguration().applyTo(config);
Utils.injectProperties(config, cfgProps);
} }
//for globalConfig section //for globalConfig section
if (dsWrap.typed()) { if (dsWrap.typed()) {
globalConfig = FlexGlobalConfig.getDefaultConfig(); globalConfig = FlexGlobalConfig.getDefaultConfig();
@ -90,15 +85,15 @@ public class MybatisAdapterFlex extends MybatisAdapterDefault {
globalConfig = new FlexGlobalConfig(); globalConfig = new FlexGlobalConfig();
} }
if (flexProperties.getGlobalConfig() != null) {
flexProperties.getGlobalConfig().applyTo(globalConfig);
}
if (globalConfig.getKeyConfig() == null) { if (globalConfig.getKeyConfig() == null) {
//如果没有给个默认值
globalConfig.setKeyConfig(new FlexGlobalConfig.KeyConfig()); globalConfig.setKeyConfig(new FlexGlobalConfig.KeyConfig());
} }
Props globalProps = dsProps.getProp("globalConfig");
if (globalProps.size() > 0) {
//尝试配置注入
Utils.injectProperties(globalConfig, globalProps);
}
globalConfig.setConfiguration(config); globalConfig.setConfiguration(config);
FlexGlobalConfig.setConfig(environment.getId(), globalConfig, false); FlexGlobalConfig.setConfig(environment.getId(), globalConfig, false);
@ -107,6 +102,12 @@ public class MybatisAdapterFlex extends MybatisAdapterDefault {
EventBus.publish(globalConfig); EventBus.publish(globalConfig);
} }
@Override
protected void loadConfiguration() {
typeAliasesBaseType = flexProperties.getTypeAliasesSuperType();
super.loadConfiguration();
}
/** /**
* 获取全局配置 * 获取全局配置
*/ */

View File

@ -20,12 +20,15 @@ import com.mybatisflex.annotation.UseDataSource;
import com.mybatisflex.core.FlexConsts; import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap; import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.datasource.DataSourceBuilder;
import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.datasource.FlexDataSource; import com.mybatisflex.core.datasource.FlexDataSource;
import com.mybatisflex.core.mybatis.FlexConfiguration; import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.core.row.RowMapperInvoker; import com.mybatisflex.core.row.RowMapperInvoker;
import com.mybatisflex.solon.MybatisFlexProperties;
import com.mybatisflex.solon.aot.MybatisRuntimeNativeRegistrar; import com.mybatisflex.solon.aot.MybatisRuntimeNativeRegistrar;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Inject; import org.noear.solon.annotation.Inject;
import org.noear.solon.aot.RuntimeNativeRegistrar; import org.noear.solon.aot.RuntimeNativeRegistrar;
import org.noear.solon.core.AppContext; import org.noear.solon.core.AppContext;
@ -35,7 +38,6 @@ import org.noear.solon.core.Props;
import org.noear.solon.core.runtime.NativeDetector; import org.noear.solon.core.runtime.NativeDetector;
import org.noear.solon.core.util.ClassUtil; import org.noear.solon.core.util.ClassUtil;
import org.noear.solon.core.util.TmplUtil; import org.noear.solon.core.util.TmplUtil;
import org.noear.solon.data.datasource.DsUtils;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.util.Map; import java.util.Map;
@ -47,9 +49,7 @@ import java.util.Map;
* @since 2.2 * @since 2.2
*/ */
public class XPluginImpl implements Plugin { public class XPluginImpl implements Plugin {
private static final String CONFIG_PREFIX = "mybatisFlex"; private static final String CONFIG_PREFIX = "mybatisFlex.";
private static final String CONFIG_DS_PREFIX = "mybatisFlex.datasource";
private static final String CONFIG_DS_DEF = "mybatisFlex.defaultDatasourceKey";
private static MybatisAdapterFlex adapterFlex; private static MybatisAdapterFlex adapterFlex;
@ -57,11 +57,20 @@ public class XPluginImpl implements Plugin {
return adapterFlex; return adapterFlex;
} }
private Props flexProps;
private MybatisFlexProperties flexProperties;
@Override @Override
public void start(AppContext context) throws Throwable { public void start(AppContext context) throws Throwable {
// 注册动态数据源的事务路由 // 注册动态数据源的事务路由
//TranManager.routing(FlexDataSource.class, new FlexDataSourceRouting()); //TranManager.routing(FlexDataSource.class, new FlexDataSourceRouting());
flexProps = context.cfg().getProp(CONFIG_PREFIX);
flexProperties = flexProps.toBean(MybatisFlexProperties.class);
if (flexProperties == null) {
flexProperties = new MybatisFlexProperties();
}
// 订阅数据源 // 订阅数据源
context.subWrapsOfType(DataSource.class, bw -> { context.subWrapsOfType(DataSource.class, bw -> {
loadDs(context, bw); loadDs(context, bw);
@ -72,18 +81,12 @@ public class XPluginImpl implements Plugin {
context.wrapAndPut(MybatisRuntimeNativeRegistrar.class); context.wrapAndPut(MybatisRuntimeNativeRegistrar.class);
} }
// 构建 mf 配置的数据源 // 构建 mf 配置的数据源
Class<?> dsDefClz = ClassUtil.loadClass("com.zaxxer.hikari.HikariDataSource"); if (Utils.isNotEmpty(flexProperties.getDatasource())) {
Props dsProps = context.cfg().getProp(CONFIG_DS_PREFIX); for (Map.Entry<String, Map<String, String>> entry : flexProperties.getDatasource().entrySet()) {
String dsDef = context.cfg().get(CONFIG_DS_DEF);
if (dsProps.size() > 0) {
Map<String, DataSource> dsMap = DsUtils.buildDsMap(dsProps, dsDefClz);
for (Map.Entry<String, DataSource> entry : dsMap.entrySet()) {
String dsName = entry.getKey(); String dsName = entry.getKey();
DataSource ds = entry.getValue(); DataSource ds = new DataSourceBuilder(entry.getValue()).build();
BeanWrap bw = context.wrap(dsName, ds, dsName.equals(dsDef)); BeanWrap bw = context.wrap(dsName, ds, dsName.equals(flexProperties.getDefaultDatasourceKey()));
loadDs(context, bw); loadDs(context, bw);
} }
} }
@ -106,7 +109,7 @@ public class XPluginImpl implements Plugin {
private void initDo(AppContext context) { private void initDo(AppContext context) {
BeanWrap dsBw = context.wrap(FlexConsts.NAME, MybatisFlexBootstrap.getInstance().getDataSource(), true); BeanWrap dsBw = context.wrap(FlexConsts.NAME, MybatisFlexBootstrap.getInstance().getDataSource(), true);
MybatisAdapterFlex dsFlex = new MybatisAdapterFlex(dsBw, context.cfg().getProp(CONFIG_PREFIX)); MybatisAdapterFlex dsFlex = new MybatisAdapterFlex(dsBw, flexProps, flexProperties);
dsFlex.mapperPublish(); dsFlex.mapperPublish();
adapterFlex = dsFlex; adapterFlex = dsFlex;

View File

@ -11,7 +11,6 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory; import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandler;
import org.noear.solon.Solon;
import org.noear.solon.Utils; import org.noear.solon.Utils;
import org.noear.solon.core.BeanWrap; import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.LifecycleIndex; import org.noear.solon.core.LifecycleIndex;
@ -39,28 +38,21 @@ import java.util.Map;
public class MybatisAdapterDefault { public class MybatisAdapterDefault {
protected static final Logger log = LoggerFactory.getLogger(MybatisAdapterDefault.class); protected static final Logger log = LoggerFactory.getLogger(MybatisAdapterDefault.class);
protected final BeanWrap dsWrap; protected BeanWrap dsWrap;
protected final Props dsProps; protected Props dsProps;
//mapper 注解验证启用 //mapper 注解验证启用
protected final boolean mapperVerifyEnabled; protected boolean mapperVerifyEnabled;
protected Configuration config; protected Configuration config;
protected SqlSessionFactory factory; protected SqlSessionFactory factory;
protected List<String> mappers = new ArrayList<>(); protected List<String> mappers = new ArrayList<>();
protected SqlSessionFactoryBuilder factoryBuilder; protected SqlSessionFactoryBuilder factoryBuilder;
/**
* 构建Sql工厂适配器使用默认的 typeAliases mappers 配置
*/
protected MybatisAdapterDefault(BeanWrap dsWrap) {
this(dsWrap, Solon.cfg().getProp("mybatis"));
}
/** /**
* 构建Sql工厂适配器使用属性配置 * 构建Sql工厂适配器使用属性配置
*/ */
protected MybatisAdapterDefault(BeanWrap dsWrap, Props dsProps) { protected void initStart(BeanWrap dsWrap, Props dsProps) {
this.dsWrap = dsWrap; this.dsWrap = dsWrap;
if (dsProps == null) { if (dsProps == null) {
this.dsProps = new Props(); this.dsProps = new Props();
@ -80,6 +72,7 @@ public class MybatisAdapterDefault {
TransactionFactory tf = new SolonManagedTransactionFactory(); TransactionFactory tf = new SolonManagedTransactionFactory();
Environment environment = new Environment(dataSourceId, tf, dataSource); Environment environment = new Environment(dataSourceId, tf, dataSource);
//1.初始化配置器
initConfiguration(environment); initConfiguration(environment);
//加载插件通过Bean //加载插件通过Bean
@ -91,11 +84,11 @@ public class MybatisAdapterDefault {
}); });
}); });
//1.分发事件推给扩展处理 //2.分发事件推给扩展处理
EventBus.publish(config); EventBus.publish(config);
//2.初始化顺序不能乱 //3.加载配置器的内容顺序不能乱
initDo(); loadConfiguration();
dsWrap.context().getBeanAsync(SqlSessionFactoryBuilder.class, bean -> { dsWrap.context().getBeanAsync(SqlSessionFactoryBuilder.class, bean -> {
factoryBuilder = bean; factoryBuilder = bean;
@ -124,19 +117,19 @@ public class MybatisAdapterDefault {
return true; return true;
} }
protected boolean isTypeAliasesKey(String key){ protected boolean isTypeAliasesKey(String key) {
return key.startsWith("typeAliases[") || key.equals("typeAliases"); return key.startsWith("typeAliases[") || key.equals("typeAliases");
} }
protected boolean isTypeHandlersKey(String key){ protected boolean isTypeHandlersKey(String key) {
return key.startsWith("typeHandlers[") || key.equals("typeHandlers"); return key.startsWith("typeHandlers[") || key.equals("typeHandlers");
} }
protected boolean isMappersKey(String key){ protected boolean isMappersKey(String key) {
return key.startsWith("mappers[") || key.equals("mappers"); return key.startsWith("mappers[") || key.equals("mappers");
} }
protected void initDo() { protected void loadConfiguration() {
//for typeAliases & typeHandlers section //for typeAliases & typeHandlers section
dsProps.forEach((k, v) -> { dsProps.forEach((k, v) -> {
if (k instanceof String && v instanceof String) { if (k instanceof String && v instanceof String) {