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.List; 031import java.util.Map; 032import java.util.concurrent.ConcurrentHashMap; 033import java.util.stream.Collectors; 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) { 204 return this.findSupportedListeners(entityClass, this.entitySetListeners); 205 } 206 207 public UpdateListener getUpdateListener(Class<?> entityClass) { 208 return entityUpdateListeners.get(entityClass); 209 } 210 211 /** 212 * 查找支持该 {@code entityClass} 的监听器 213 * @param entityClass 实体class 214 * @param listenerMap 监听器map 215 * @return 符合条件的监听器 216 * @param <T> 监听器类型 217 */ 218 public <T extends Listener> List<T> findSupportedListeners(Class<?> entityClass, Map<Class<?>, T> listenerMap) { 219 return listenerMap.entrySet().stream() 220 .filter(entry -> entry.getKey().isAssignableFrom(entityClass)) 221 .map(Map.Entry::getValue) 222 .collect(Collectors.toList()); 223 } 224 225 /** 226 * 获取支持该 {@code entityClass} 的update监听器 227 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 228 * 229 * @param entityClass 实体class 230 * @return UpdateListener 231 */ 232 public List<UpdateListener> getSupportedUpdateListener(Class<?> entityClass) { 233 return this.findSupportedListeners(entityClass, this.entityUpdateListeners); 234 } 235 236 237 public InsertListener getInsertListener(Class<?> entityClass) { 238 return entityInsertListeners.get(entityClass); 239 } 240 241 /** 242 * 获取支持该 {@code entityClass} 的insert监听器 243 * <p>当registerClass是entityClass的本身或其超类时,则视为支持</p> 244 * 245 * @param entityClass 实体class 246 * @return InsertListener 247 */ 248 public List<InsertListener> getSupportedInsertListener(Class<?> entityClass) { 249 return this.findSupportedListeners(entityClass, this.entityInsertListeners); 250 } 251 252 public Object getNormalValueOfLogicDelete() { 253 return normalValueOfLogicDelete; 254 } 255 256 public void setNormalValueOfLogicDelete(Object normalValueOfLogicDelete) { 257 FlexAssert.notNull(normalValueOfLogicDelete, "normalValueOfLogicDelete"); 258 this.normalValueOfLogicDelete = normalValueOfLogicDelete; 259 } 260 261 public Object getDeletedValueOfLogicDelete() { 262 return deletedValueOfLogicDelete; 263 } 264 265 public void setDeletedValueOfLogicDelete(Object deletedValueOfLogicDelete) { 266 FlexAssert.notNull(deletedValueOfLogicDelete, "deletedValueOfLogicDelete"); 267 this.deletedValueOfLogicDelete = deletedValueOfLogicDelete; 268 } 269 270 public int getDefaultPageSize() { 271 return defaultPageSize; 272 } 273 274 public void setDefaultPageSize(int defaultPageSize) { 275 this.defaultPageSize = defaultPageSize; 276 } 277 278 public int getDefaultRelationQueryDepth() { 279 return defaultRelationQueryDepth; 280 } 281 282 public void setDefaultRelationQueryDepth(int defaultRelationQueryDepth) { 283 this.defaultRelationQueryDepth = defaultRelationQueryDepth; 284 } 285 286 public String getLogicDeleteColumn() { 287 return logicDeleteColumn; 288 } 289 290 public void setLogicDeleteColumn(String logicDeleteColumn) { 291 this.logicDeleteColumn = logicDeleteColumn; 292 } 293 294 public String getTenantColumn() { 295 return tenantColumn; 296 } 297 298 public void setTenantColumn(String tenantColumn) { 299 this.tenantColumn = tenantColumn; 300 } 301 302 public String getVersionColumn() { 303 return versionColumn; 304 } 305 306 public void setVersionColumn(String versionColumn) { 307 this.versionColumn = versionColumn; 308 } 309 310 public FlexDataSource getDataSource() { 311 return (FlexDataSource) getConfiguration().getEnvironment().getDataSource(); 312 } 313 314 public static ConcurrentHashMap<String, FlexGlobalConfig> getGlobalConfigs() { 315 return globalConfigs; 316 } 317 318 public static void setGlobalConfigs(ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs) { 319 FlexGlobalConfig.globalConfigs = globalConfigs; 320 } 321 322 323 /** 324 * 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置 325 */ 326 public static class KeyConfig { 327 328 private KeyType keyType; 329 private String value; 330 private boolean before = true; 331 332 public KeyType getKeyType() { 333 return keyType; 334 } 335 336 public void setKeyType(KeyType keyType) { 337 this.keyType = keyType; 338 } 339 340 public String getValue() { 341 return value; 342 } 343 344 public void setValue(String value) { 345 this.value = value; 346 } 347 348 public boolean isBefore() { 349 return before; 350 } 351 352 public void setBefore(boolean before) { 353 this.before = before; 354 } 355 356 } 357 358 359 /////static factory methods///// 360 private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>(); 361 private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig(); 362 363 public static FlexGlobalConfig getDefaultConfig() { 364 return defaultConfig; 365 } 366 367 public static void setDefaultConfig(FlexGlobalConfig config) { 368 if (config == null) { 369 throw new NullPointerException("config must not be null."); 370 } 371 defaultConfig = config; 372 } 373 374 public static FlexGlobalConfig getConfig(Configuration configuration) { 375 return getConfig(configuration.getEnvironment().getId()); 376 } 377 378 public static FlexGlobalConfig getConfig(String environmentId) { 379 return globalConfigs.get(environmentId); 380 } 381 382 383 /** 384 * 设置全局配置 385 * 386 * @param id 环境id 387 * @param config 全局配置 388 * @param isDefault 自动指定默认全局配置(在多源时,方便由注解指定默认源) 389 */ 390 public static synchronized void setConfig(String id, FlexGlobalConfig config, boolean isDefault) { 391 if (isDefault) { 392 defaultConfig.setSqlSessionFactory(config.sqlSessionFactory); 393 defaultConfig.setConfiguration(config.configuration); 394 } 395 396 globalConfigs.put(id, isDefault ? defaultConfig : config); 397 } 398 399}