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