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