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