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