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