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