001/* 002 * Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core; 017 018import com.mybatisflex.annotation.InsertListener; 019import com.mybatisflex.annotation.KeyType; 020import com.mybatisflex.annotation.Listener; 021import com.mybatisflex.annotation.SetListener; 022import com.mybatisflex.annotation.UpdateListener; 023import com.mybatisflex.core.datasource.DataSourceMissingHandler; 024import com.mybatisflex.core.datasource.FlexDataSource; 025import com.mybatisflex.core.dialect.DbType; 026import com.mybatisflex.core.exception.FlexAssert; 027import com.mybatisflex.core.mybatis.UnMappedColumnHandler; 028import org.apache.ibatis.session.Configuration; 029import org.apache.ibatis.session.SqlSessionFactory; 030 031import javax.sql.DataSource; 032import java.util.ArrayList; 033import java.util.List; 034import java.util.Map; 035import java.util.concurrent.ConcurrentHashMap; 036import java.util.stream.Collectors; 037 038/** 039 * 全局配置文件 040 */ 041public class FlexGlobalConfig { 042 043 /** 044 * 启动是否打印 banner 和 版本号 045 */ 046 private boolean printBanner = true; 047 048 /** 049 * 默认使用 Mysql 数据库类型 050 */ 051 private DbType dbType = DbType.MYSQL; 052 053 /** 054 * Mybatis 配置 055 */ 056 private Configuration configuration; 057 058 /** 059 * 创建好的 sqlSessionFactory 060 */ 061 private SqlSessionFactory sqlSessionFactory; 062 063 /** 064 * 全局的 ID 生成策略配置,当 @Id 未配置 或者 配置 KeyType 为 None 时 065 * 使用当前全局配置 066 */ 067 private KeyConfig keyConfig; 068 069 /** 070 * entity 的监听器 071 */ 072 private Map<Class<?>, List<SetListener>> entitySetListeners = new ConcurrentHashMap<>(); 073 private Map<Class<?>, List<UpdateListener>> entityUpdateListeners = new ConcurrentHashMap<>(); 074 private Map<Class<?>, List<InsertListener>> entityInsertListeners = new ConcurrentHashMap<>(); 075 076 077 /** 078 * 逻辑删除的相关配置 079 */ 080 private Object normalValueOfLogicDelete = FlexConsts.LOGIC_DELETE_NORMAL; 081 private Object deletedValueOfLogicDelete = FlexConsts.LOGIC_DELETE_DELETED; 082 083 /** 084 * 分页查询时,默认每页显示的数据数量。 085 */ 086 private int defaultPageSize = 10; 087 088 /** 089 * 分页查询时,默认每页显示的数据数量最大限制。 090 */ 091 private int defaultMaxPageSize = Integer.MAX_VALUE; 092 093 094 /** 095 * 默认的 Relation 注解查询深度 096 */ 097 private int defaultRelationQueryDepth = 2; 098 099 /** 100 * 默认的逻辑删除字段,允许设置 {@code null} 忽略匹配。 101 */ 102 private String logicDeleteColumn; 103 104 /** 105 * 默认的多租户字段,允许设置 {@code null} 忽略匹配。 106 */ 107 private String tenantColumn; 108 109 /** 110 * 默认的乐观锁字段,允许设置 {@code null} 忽略匹配。 111 */ 112 private String versionColumn; 113 114 /** 115 * 全局忽略 @Table 中配置的 schema 116 */ 117 private boolean ignoreSchema = false; 118 119 /** 120 * 未匹配列处理器 121 */ 122 private UnMappedColumnHandler unMappedColumnHandler; 123 124 /** 125 * 数据源缺失处理器 126 */ 127 private DataSourceMissingHandler dataSourceMissingHandler; 128 129 public boolean isPrintBanner() { 130 return printBanner; 131 } 132 133 public void setPrintBanner(boolean printBanner) { 134 this.printBanner = printBanner; 135 } 136 137 public DbType getDbType() { 138 return dbType; 139 } 140 141 public void setDbType(DbType dbType) { 142 this.dbType = dbType; 143 } 144 145 public Configuration getConfiguration() { 146 return configuration; 147 } 148 149 public void setConfiguration(Configuration configuration) { 150 this.configuration = configuration; 151 DataSource dataSource = configuration.getEnvironment().getDataSource(); 152 if (dataSource instanceof FlexDataSource) { 153 this.dbType = ((FlexDataSource) dataSource).getDefaultDbType(); 154 } 155 } 156 157 public SqlSessionFactory getSqlSessionFactory() { 158 return sqlSessionFactory; 159 } 160 161 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 162 this.sqlSessionFactory = sqlSessionFactory; 163 } 164 165 public KeyConfig getKeyConfig() { 166 return keyConfig; 167 } 168 169 public void setKeyConfig(KeyConfig keyConfig) { 170 this.keyConfig = keyConfig; 171 } 172 173 public Map<Class<?>, List<SetListener>> getEntitySetListeners() { 174 return entitySetListeners; 175 } 176 177 public void setEntitySetListeners(Map<Class<?>, List<SetListener>> entitySetListeners) { 178 this.entitySetListeners = entitySetListeners; 179 } 180 181 public Map<Class<?>, List<UpdateListener>> getEntityUpdateListeners() { 182 return entityUpdateListeners; 183 } 184 185 public void setEntityUpdateListeners(Map<Class<?>, List<UpdateListener>> entityUpdateListeners) { 186 this.entityUpdateListeners = entityUpdateListeners; 187 } 188 189 public Map<Class<?>, List<InsertListener>> getEntityInsertListeners() { 190 return entityInsertListeners; 191 } 192 193 public void setEntityInsertListeners(Map<Class<?>, List<InsertListener>> entityInsertListeners) { 194 this.entityInsertListeners = entityInsertListeners; 195 } 196 197 public void registerSetListener(SetListener listener, Class<?>... classes) { 198 for (Class<?> aClass : classes) { 199 entitySetListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 200 } 201 } 202 203 public void registerUpdateListener(UpdateListener listener, Class<?>... classes) { 204 for (Class<?> aClass : classes) { 205 entityUpdateListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 206 } 207 } 208 209 public void registerInsertListener(InsertListener listener, Class<?>... classes) { 210 for (Class<?> aClass : classes) { 211 entityInsertListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 212 } 213 } 214 215 public List<SetListener> getSetListener(Class<?> entityClass) { 216 return entitySetListeners.get(entityClass); 217 } 218 219 /** 220 * 获取支持该 {@code entityClass} 的set监听器 221 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 222 * 223 * @param entityClass 实体class 224 * @return UpdateListener 225 */ 226 public List<SetListener> getSupportedSetListener(Class<?> entityClass) { 227 return this.findSupportedListeners(entityClass, this.entitySetListeners); 228 } 229 230 public List<UpdateListener> getUpdateListener(Class<?> entityClass) { 231 return entityUpdateListeners.get(entityClass); 232 } 233 234 /** 235 * 查找支持该 {@code entityClass} 的监听器 236 * 237 * @param entityClass 实体class 238 * @param listenerMap 监听器map 239 * @param <T> 监听器类型 240 * @return 符合条件的监听器 241 */ 242 public <T extends Listener> List<T> findSupportedListeners(Class<?> entityClass, Map<Class<?>, List<T>> listenerMap) { 243 return listenerMap.entrySet() 244 .stream() 245 .filter(entry -> entry.getKey().isAssignableFrom(entityClass)) 246 .flatMap(e -> e.getValue().stream()) 247 .collect(Collectors.toList()); 248 } 249 250 /** 251 * 获取支持该 {@code entityClass} 的update监听器 252 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 253 * 254 * @param entityClass 实体class 255 * @return UpdateListener 256 */ 257 public List<UpdateListener> getSupportedUpdateListener(Class<?> entityClass) { 258 return this.findSupportedListeners(entityClass, this.entityUpdateListeners); 259 } 260 261 262 public List<InsertListener> getInsertListener(Class<?> entityClass) { 263 return entityInsertListeners.get(entityClass); 264 } 265 266 /** 267 * 获取支持该 {@code entityClass} 的insert监听器 268 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 269 * 270 * @param entityClass 实体class 271 * @return InsertListener 272 */ 273 public List<InsertListener> getSupportedInsertListener(Class<?> entityClass) { 274 return this.findSupportedListeners(entityClass, this.entityInsertListeners); 275 } 276 277 public Object getNormalValueOfLogicDelete() { 278 return normalValueOfLogicDelete; 279 } 280 281 public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) { 282 FlexAssert.notNull(normalValueOfLogicDelete, "normalValueOfLogicDelete"); 283 this.normalValueOfLogicDelete = normalValueOfLogicDelete; 284 } 285 286 public Object getDeletedValueOfLogicDelete() { 287 return deletedValueOfLogicDelete; 288 } 289 290 public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) { 291 FlexAssert.notNull(deletedValueOfLogicDelete, "deletedValueOfLogicDelete"); 292 this.deletedValueOfLogicDelete = deletedValueOfLogicDelete; 293 } 294 295 public int getDefaultPageSize() { 296 return defaultPageSize; 297 } 298 299 public void setDefaultPageSize(int defaultPageSize) { 300 this.defaultPageSize = defaultPageSize; 301 } 302 303 public int getDefaultMaxPageSize() { 304 return defaultMaxPageSize; 305 } 306 307 public void setDefaultMaxPageSize(int defaultMaxPageSize) { 308 this.defaultMaxPageSize = defaultMaxPageSize; 309 } 310 311 public int getDefaultRelationQueryDepth() { 312 return defaultRelationQueryDepth; 313 } 314 315 public void setDefaultRelationQueryDepth(int defaultRelationQueryDepth) { 316 this.defaultRelationQueryDepth = defaultRelationQueryDepth; 317 } 318 319 public String getLogicDeleteColumn() { 320 return logicDeleteColumn; 321 } 322 323 public void setLogicDeleteColumn(String logicDeleteColumn) { 324 this.logicDeleteColumn = logicDeleteColumn; 325 } 326 327 public String getTenantColumn() { 328 return tenantColumn; 329 } 330 331 public void setTenantColumn(String tenantColumn) { 332 this.tenantColumn = tenantColumn; 333 } 334 335 public String getVersionColumn() { 336 return versionColumn; 337 } 338 339 public void setVersionColumn(String versionColumn) { 340 this.versionColumn = versionColumn; 341 } 342 343 public boolean isIgnoreSchema() { 344 return ignoreSchema; 345 } 346 347 public void setIgnoreSchema(boolean ignoreSchema) { 348 this.ignoreSchema = ignoreSchema; 349 } 350 351 public UnMappedColumnHandler getUnMappedColumnHandler() { 352 return unMappedColumnHandler; 353 } 354 355 public void setUnMappedColumnHandler(UnMappedColumnHandler unMappedColumnHandler) { 356 this.unMappedColumnHandler = unMappedColumnHandler; 357 } 358 359 public FlexDataSource getDataSource() { 360 return (FlexDataSource) getConfiguration().getEnvironment().getDataSource(); 361 } 362 363 public static ConcurrentHashMap<String, FlexGlobalConfig> getGlobalConfigs() { 364 return globalConfigs; 365 } 366 367 public static void setGlobalConfigs(ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs) { 368 FlexGlobalConfig.globalConfigs = globalConfigs; 369 } 370 371 /** 372 * 获取数据源缺失处理器。 373 * @return DataSourceMissingHandler 数据源缺失处理器实例,用于自定义处理逻辑(如:记录日志、抛出异常或提供默认数据源)。 374 */ 375 public DataSourceMissingHandler getDataSourceMissingHandler() { 376 return dataSourceMissingHandler; 377 } 378 379 /** 380 * 设置获取数据源缺失处理器。 381 * @param dataSourceMissingHandler 数据源缺失处理器实例,用于自定义处理逻辑(如:记录日志、抛出异常或提供默认数据源)。 382 */ 383 public void setDataSourceMissingHandler(final DataSourceMissingHandler dataSourceMissingHandler) { 384 this.dataSourceMissingHandler = dataSourceMissingHandler; 385 } 386 387 /** 388 * 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置 389 */ 390 public static class KeyConfig { 391 392 private KeyType keyType; 393 private String value; 394 private boolean before = true; 395 396 public KeyType getKeyType() { 397 return keyType; 398 } 399 400 public void setKeyType(KeyType keyType) { 401 this.keyType = keyType; 402 } 403 404 public String getValue() { 405 return value; 406 } 407 408 public void setValue(String value) { 409 this.value = value; 410 } 411 412 public boolean isBefore() { 413 return before; 414 } 415 416 public void setBefore(boolean before) { 417 this.before = before; 418 } 419 420 } 421 422 423 /// //static factory methods///// 424 private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>(); 425 private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig(); 426 427 public static FlexGlobalConfig getDefaultConfig() { 428 return defaultConfig; 429 } 430 431 public static void setDefaultConfig(FlexGlobalConfig config) { 432 if (config == null) { 433 throw new NullPointerException("config must not be null."); 434 } 435 defaultConfig = config; 436 } 437 438 public static FlexGlobalConfig getConfig(Configuration configuration) { 439 return getConfig(configuration.getEnvironment().getId()); 440 } 441 442 public static FlexGlobalConfig getConfig(String environmentId) { 443 return globalConfigs.get(environmentId); 444 } 445 446 447 /** 448 * 设置全局配置 449 * 450 * @param id 环境id 451 * @param config 全局配置 452 * @param isDefault 自动指定默认全局配置(在多源时,方便由注解指定默认源) 453 */ 454 public static synchronized void setConfig(String id, FlexGlobalConfig config, boolean isDefault) { 455 if (isDefault) { 456 defaultConfig.setSqlSessionFactory(config.sqlSessionFactory); 457 defaultConfig.setConfiguration(config.configuration); 458 } 459 460 globalConfigs.put(id, config); 461 } 462 463}