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 * 未匹配列处理器 115 */ 116 private static UnMappedColumnHandler unMappedColumnHandler; 117 118 public boolean isPrintBanner() { 119 return printBanner; 120 } 121 122 public void setPrintBanner(boolean printBanner) { 123 this.printBanner = printBanner; 124 } 125 126 public DbType getDbType() { 127 return dbType; 128 } 129 130 public void setDbType(DbType dbType) { 131 this.dbType = dbType; 132 } 133 134 public Configuration getConfiguration() { 135 return configuration; 136 } 137 138 public void setConfiguration(Configuration configuration) { 139 this.configuration = configuration; 140 DataSource dataSource = configuration.getEnvironment().getDataSource(); 141 if (dataSource instanceof FlexDataSource) { 142 this.dbType = ((FlexDataSource) dataSource).getDefaultDbType(); 143 } 144 } 145 146 public SqlSessionFactory getSqlSessionFactory() { 147 return sqlSessionFactory; 148 } 149 150 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 151 this.sqlSessionFactory = sqlSessionFactory; 152 } 153 154 public KeyConfig getKeyConfig() { 155 return keyConfig; 156 } 157 158 public void setKeyConfig(KeyConfig keyConfig) { 159 this.keyConfig = keyConfig; 160 } 161 162 public Map<Class<?>, List<SetListener>> getEntitySetListeners() { 163 return entitySetListeners; 164 } 165 166 public void setEntitySetListeners(Map<Class<?>, List<SetListener>> entitySetListeners) { 167 this.entitySetListeners = entitySetListeners; 168 } 169 170 public Map<Class<?>, List<UpdateListener>> getEntityUpdateListeners() { 171 return entityUpdateListeners; 172 } 173 174 public void setEntityUpdateListeners(Map<Class<?>, List<UpdateListener>> entityUpdateListeners) { 175 this.entityUpdateListeners = entityUpdateListeners; 176 } 177 178 public Map<Class<?>, List<InsertListener>> getEntityInsertListeners() { 179 return entityInsertListeners; 180 } 181 182 public void setEntityInsertListeners(Map<Class<?>, List<InsertListener>> entityInsertListeners) { 183 this.entityInsertListeners = entityInsertListeners; 184 } 185 186 public void registerSetListener(SetListener listener, Class<?>... classes) { 187 for (Class<?> aClass : classes) { 188 entitySetListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 189 } 190 } 191 192 public void registerUpdateListener(UpdateListener listener, Class<?>... classes) { 193 for (Class<?> aClass : classes) { 194 entityUpdateListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 195 } 196 } 197 198 public void registerInsertListener(InsertListener listener, Class<?>... classes) { 199 for (Class<?> aClass : classes) { 200 entityInsertListeners.computeIfAbsent(aClass, k -> new ArrayList<>()).add(listener); 201 } 202 } 203 204 public List<SetListener> getSetListener(Class<?> entityClass) { 205 return entitySetListeners.get(entityClass); 206 } 207 208 /** 209 * 获取支持该 {@code entityClass} 的set监听器 210 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 211 * 212 * @param entityClass 实体class 213 * @return UpdateListener 214 */ 215 public List<SetListener> getSupportedSetListener(Class<?> entityClass) { 216 return this.findSupportedListeners(entityClass, this.entitySetListeners); 217 } 218 219 public List<UpdateListener> getUpdateListener(Class<?> entityClass) { 220 return entityUpdateListeners.get(entityClass); 221 } 222 223 /** 224 * 查找支持该 {@code entityClass} 的监听器 225 * 226 * @param entityClass 实体class 227 * @param listenerMap 监听器map 228 * @param <T> 监听器类型 229 * @return 符合条件的监听器 230 */ 231 public <T extends Listener> List<T> findSupportedListeners(Class<?> entityClass, Map<Class<?>, List<T>> listenerMap) { 232 return listenerMap.entrySet() 233 .stream() 234 .filter(entry -> entry.getKey().isAssignableFrom(entityClass)) 235 .flatMap(e -> e.getValue().stream()) 236 .collect(Collectors.toList()); 237 } 238 239 /** 240 * 获取支持该 {@code entityClass} 的update监听器 241 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 242 * 243 * @param entityClass 实体class 244 * @return UpdateListener 245 */ 246 public List<UpdateListener> getSupportedUpdateListener(Class<?> entityClass) { 247 return this.findSupportedListeners(entityClass, this.entityUpdateListeners); 248 } 249 250 251 public List<InsertListener> getInsertListener(Class<?> entityClass) { 252 return entityInsertListeners.get(entityClass); 253 } 254 255 /** 256 * 获取支持该 {@code entityClass} 的insert监听器 257 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 258 * 259 * @param entityClass 实体class 260 * @return InsertListener 261 */ 262 public List<InsertListener> getSupportedInsertListener(Class<?> entityClass) { 263 return this.findSupportedListeners(entityClass, this.entityInsertListeners); 264 } 265 266 public Object getNormalValueOfLogicDelete() { 267 return normalValueOfLogicDelete; 268 } 269 270 public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) { 271 FlexAssert.notNull(normalValueOfLogicDelete, "normalValueOfLogicDelete"); 272 this.normalValueOfLogicDelete = normalValueOfLogicDelete; 273 } 274 275 public Object getDeletedValueOfLogicDelete() { 276 return deletedValueOfLogicDelete; 277 } 278 279 public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) { 280 FlexAssert.notNull(deletedValueOfLogicDelete, "deletedValueOfLogicDelete"); 281 this.deletedValueOfLogicDelete = deletedValueOfLogicDelete; 282 } 283 284 public int getDefaultPageSize() { 285 return defaultPageSize; 286 } 287 288 public void setDefaultPageSize(int defaultPageSize) { 289 this.defaultPageSize = defaultPageSize; 290 } 291 292 public int getDefaultMaxPageSize() { 293 return defaultMaxPageSize; 294 } 295 296 public void setDefaultMaxPageSize(int defaultMaxPageSize) { 297 this.defaultMaxPageSize = defaultMaxPageSize; 298 } 299 300 public int getDefaultRelationQueryDepth() { 301 return defaultRelationQueryDepth; 302 } 303 304 public void setDefaultRelationQueryDepth(int defaultRelationQueryDepth) { 305 this.defaultRelationQueryDepth = defaultRelationQueryDepth; 306 } 307 308 public String getLogicDeleteColumn() { 309 return logicDeleteColumn; 310 } 311 312 public void setLogicDeleteColumn(String logicDeleteColumn) { 313 this.logicDeleteColumn = logicDeleteColumn; 314 } 315 316 public String getTenantColumn() { 317 return tenantColumn; 318 } 319 320 public void setTenantColumn(String tenantColumn) { 321 this.tenantColumn = tenantColumn; 322 } 323 324 public String getVersionColumn() { 325 return versionColumn; 326 } 327 328 public void setVersionColumn(String versionColumn) { 329 this.versionColumn = versionColumn; 330 } 331 332 public static UnMappedColumnHandler getUnMappedColumnHandler() { 333 return unMappedColumnHandler; 334 } 335 336 public void setUnMappedColumnHandler(UnMappedColumnHandler unMappedColumnHandler) { 337 this.unMappedColumnHandler = unMappedColumnHandler; 338 } 339 340 public FlexDataSource getDataSource() { 341 return (FlexDataSource) getConfiguration().getEnvironment().getDataSource(); 342 } 343 344 public static ConcurrentHashMap<String, FlexGlobalConfig> getGlobalConfigs() { 345 return globalConfigs; 346 } 347 348 public static void setGlobalConfigs(ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs) { 349 FlexGlobalConfig.globalConfigs = globalConfigs; 350 } 351 352 353 /** 354 * 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置 355 */ 356 public static class KeyConfig { 357 358 private KeyType keyType; 359 private String value; 360 private boolean before = true; 361 362 public KeyType getKeyType() { 363 return keyType; 364 } 365 366 public void setKeyType(KeyType keyType) { 367 this.keyType = keyType; 368 } 369 370 public String getValue() { 371 return value; 372 } 373 374 public void setValue(String value) { 375 this.value = value; 376 } 377 378 public boolean isBefore() { 379 return before; 380 } 381 382 public void setBefore(boolean before) { 383 this.before = before; 384 } 385 386 } 387 388 389 /////static factory methods///// 390 private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>(); 391 private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig(); 392 393 public static FlexGlobalConfig getDefaultConfig() { 394 return defaultConfig; 395 } 396 397 public static void setDefaultConfig(FlexGlobalConfig config) { 398 if (config == null) { 399 throw new NullPointerException("config must not be null."); 400 } 401 defaultConfig = config; 402 } 403 404 public static FlexGlobalConfig getConfig(Configuration configuration) { 405 return getConfig(configuration.getEnvironment().getId()); 406 } 407 408 public static FlexGlobalConfig getConfig(String environmentId) { 409 return globalConfigs.get(environmentId); 410 } 411 412 413 /** 414 * 设置全局配置 415 * 416 * @param id 环境id 417 * @param config 全局配置 418 * @param isDefault 自动指定默认全局配置(在多源时,方便由注解指定默认源) 419 */ 420 public static synchronized void setConfig(String id, FlexGlobalConfig config, boolean isDefault) { 421 if (isDefault) { 422 defaultConfig.setSqlSessionFactory(config.sqlSessionFactory); 423 defaultConfig.setConfiguration(config.configuration); 424 } 425 426 globalConfigs.put(id, isDefault ? defaultConfig : config); 427 } 428 429}