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 while (setListener == null && childClass != null) { 225 setListener = entitySetListeners.get(childClass); 226 childClass = childClass.getSuperclass(); 227 } 228 229 if (setListener != null) { 230 listeners.put(childClass, setListener); 231 } 232 } 233 234 235 public UpdateListener getUpdateListener(Class<?> entityClass) { 236 return entityUpdateListeners.get(entityClass); 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, boolean interfaceOnly) { 247 248 Map<Class<?>, UpdateListener> map = new HashMap<>(); 249 if (!interfaceOnly) { 250 doGetSupportedUpdateListener(entityClass, map); 251 } 252 253 while (entityClass.getSuperclass() != null) { 254 Class<?>[] interfaces = entityClass.getInterfaces(); 255 for (Class<?> interfaceClass : interfaces) { 256 doGetSupportedUpdateListener(interfaceClass, map); 257 } 258 entityClass = entityClass.getSuperclass(); 259 } 260 261 return new ArrayList<>(map.values()); 262 } 263 264 265 private void doGetSupportedUpdateListener(Class<?> childClass, Map<Class<?>, UpdateListener> listeners) { 266 UpdateListener updateListener = null; 267 while (updateListener == null && childClass != null) { 268 updateListener = entityUpdateListeners.get(childClass); 269 childClass = childClass.getSuperclass(); 270 } 271 272 if (updateListener != null) { 273 listeners.put(childClass, updateListener); 274 } 275 } 276 277 278 public InsertListener getInsertListener(Class<?> entityClass) { 279 return entityInsertListeners.get(entityClass); 280 } 281 282 /** 283 * 获取支持该 {@code entityClass} 的insert监听器 284 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 285 * 286 * @param entityClass 实体class 287 * @return InsertListener 288 */ 289 public List<InsertListener> getSupportedInsertListener(Class<?> entityClass, boolean interfaceOnly) { 290 291 Map<Class<?>, InsertListener> map = new HashMap<>(); 292 if (!interfaceOnly) { 293 doGetSupportedInsertListener(entityClass, map); 294 } 295 296 while (entityClass.getSuperclass() != null) { 297 Class<?>[] interfaces = entityClass.getInterfaces(); 298 for (Class<?> interfaceClass : interfaces) { 299 doGetSupportedInsertListener(interfaceClass, map); 300 } 301 entityClass = entityClass.getSuperclass(); 302 } 303 304 return new ArrayList<>(map.values()); 305 } 306 307 308 private void doGetSupportedInsertListener(Class<?> childClass, Map<Class<?>, InsertListener> listeners) { 309 InsertListener insertListener = null; 310 while (insertListener == null && childClass != null) { 311 insertListener = entityInsertListeners.get(childClass); 312 childClass = childClass.getSuperclass(); 313 } 314 315 if (insertListener != null) { 316 listeners.put(childClass, insertListener); 317 } 318 } 319 320 321 public Object getNormalValueOfLogicDelete() { 322 return normalValueOfLogicDelete; 323 } 324 325 public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) { 326 FlexAssert.notNull(normalValueOfLogicDelete, "normalValueOfLogicDelete"); 327 this.normalValueOfLogicDelete = normalValueOfLogicDelete; 328 } 329 330 public Object getDeletedValueOfLogicDelete() { 331 return deletedValueOfLogicDelete; 332 } 333 334 public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) { 335 FlexAssert.notNull(deletedValueOfLogicDelete, "deletedValueOfLogicDelete"); 336 this.deletedValueOfLogicDelete = deletedValueOfLogicDelete; 337 } 338 339 public int getDefaultPageSize() { 340 return defaultPageSize; 341 } 342 343 public void setDefaultPageSize(int defaultPageSize) { 344 this.defaultPageSize = defaultPageSize; 345 } 346 347 public int getDefaultRelationQueryDepth() { 348 return defaultRelationQueryDepth; 349 } 350 351 public void setDefaultRelationQueryDepth(int defaultRelationQueryDepth) { 352 this.defaultRelationQueryDepth = defaultRelationQueryDepth; 353 } 354 355 public String getLogicDeleteColumn() { 356 return logicDeleteColumn; 357 } 358 359 public void setLogicDeleteColumn(String logicDeleteColumn) { 360 this.logicDeleteColumn = logicDeleteColumn; 361 } 362 363 public String getTenantColumn() { 364 return tenantColumn; 365 } 366 367 public void setTenantColumn(String tenantColumn) { 368 this.tenantColumn = tenantColumn; 369 } 370 371 public String getVersionColumn() { 372 return versionColumn; 373 } 374 375 public void setVersionColumn(String versionColumn) { 376 this.versionColumn = versionColumn; 377 } 378 379 public FlexDataSource getDataSource() { 380 return (FlexDataSource) getConfiguration().getEnvironment().getDataSource(); 381 } 382 383 public static ConcurrentHashMap<String, FlexGlobalConfig> getGlobalConfigs() { 384 return globalConfigs; 385 } 386 387 public static void setGlobalConfigs(ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs) { 388 FlexGlobalConfig.globalConfigs = globalConfigs; 389 } 390 391 392 /** 393 * 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置 394 */ 395 public static class KeyConfig { 396 397 private KeyType keyType; 398 private String value; 399 private boolean before = true; 400 401 public KeyType getKeyType() { 402 return keyType; 403 } 404 405 public void setKeyType(KeyType keyType) { 406 this.keyType = keyType; 407 } 408 409 public String getValue() { 410 return value; 411 } 412 413 public void setValue(String value) { 414 this.value = value; 415 } 416 417 public boolean isBefore() { 418 return before; 419 } 420 421 public void setBefore(boolean before) { 422 this.before = before; 423 } 424 425 } 426 427 428 /////static factory methods///// 429 private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>(); 430 private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig(); 431 432 public static FlexGlobalConfig getDefaultConfig() { 433 return defaultConfig; 434 } 435 436 public static void setDefaultConfig(FlexGlobalConfig config) { 437 if (config == null) { 438 throw new NullPointerException("config must not be null."); 439 } 440 defaultConfig = config; 441 } 442 443 public static FlexGlobalConfig getConfig(Configuration configuration) { 444 return getConfig(configuration.getEnvironment().getId()); 445 } 446 447 public static FlexGlobalConfig getConfig(String environmentId) { 448 return globalConfigs.get(environmentId); 449 } 450 451 452 /** 453 * 设置全局配置 454 * 455 * @param id 环境id 456 * @param config 全局配置 457 * @param isDefault 自动指定默认全局配置(在多源时,方便由注解指定默认源) 458 */ 459 public static synchronized void setConfig(String id, FlexGlobalConfig config, boolean isDefault) { 460 if (isDefault) { 461 defaultConfig.setSqlSessionFactory(config.sqlSessionFactory); 462 defaultConfig.setConfiguration(config.configuration); 463 } 464 465 globalConfigs.put(id, isDefault ? defaultConfig : config); 466 } 467 468}