All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.baomidou.mybatisplus.core.MybatisConfiguration Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2011-2021, baomidou ([email protected]).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.baomidou.mybatisplus.core;

import com.baomidou.mybatisplus.core.handlers.CompositeEnumTypeHandler;
import com.baomidou.mybatisplus.core.mapper.Mapper;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import lombok.Getter;
import lombok.Setter;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.type.TypeHandler;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * replace default Configuration class
 * 

Caratacus 2016/9/25 replace mapperRegistry

* * @author hubin * @since 2016-01-23 */ public class MybatisConfiguration extends Configuration { private static final Log logger = LogFactory.getLog(MybatisConfiguration.class); /** * Mapper 注册 */ protected final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this); protected final Map caches = new StrictMap<>("Caches collection"); protected final Map resultMaps = new StrictMap<>("Result Maps collection"); protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection"); protected final Map keyGenerators = new StrictMap<>("Key Generators collection"); protected final Map sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers"); protected final Map mappedStatements = new StrictMap("Mapped Statements collection") .conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource()); /** * 是否生成短key缓存 * * @since 3.4.0 */ @Setter @Getter private boolean useGeneratedShortKey = true; public MybatisConfiguration(Environment environment) { this(); this.environment = environment; } /** * 初始化调用 */ public MybatisConfiguration() { super(); this.mapUnderscoreToCamelCase = true; typeHandlerRegistry.setDefaultEnumTypeHandler(CompositeEnumTypeHandler.class); languageRegistry.setDefaultDriverClass(MybatisXMLLanguageDriver.class); } /** * MybatisPlus 加载 SQL 顺序: *

1、加载 XML中的 SQL

*

2、加载 SqlProvider 中的 SQL

*

3、XmlSql 与 SqlProvider不能包含相同的 SQL

*

调整后的 SQL优先级:XmlSql > sqlProvider > CurdSql

*/ @Override public void addMappedStatement(MappedStatement ms) { if (mappedStatements.containsKey(ms.getId())) { /* * 说明已加载了xml中的节点; 忽略mapper中的 SqlProvider 数据 */ logger.error("mapper[" + ms.getId() + "] is ignored, because it exists, maybe from xml file"); return; } mappedStatements.put(ms.getId(), ms); } /** * 使用自己的 MybatisMapperRegistry */ @Override public MapperRegistry getMapperRegistry() { return mybatisMapperRegistry; } /** * 使用自己的 MybatisMapperRegistry */ @Override public void addMapper(Class type) { mybatisMapperRegistry.addMapper(type); } /** * 新增注入新的 Mapper 信息,新增前会清理之前的缓存信息 * * @param type Mapper Type * @param */ public void addNewMapper(Class type) { this.removeMapper(type); this.addMapper(type); } /** * 移除 Mapper 相关缓存,支持 GroovyClassLoader 动态注入 Mapper * * @param type Mapper Type * @param */ public void removeMapper(Class type) { // TODO Set mapperRegistryCache = GlobalConfigUtils.getGlobalConfig(this).getMapperRegistryCache(); final String mapperType = type.toString(); if (mapperRegistryCache.contains(mapperType)) { // 清空实体表信息映射信息 TableInfoHelper.remove(ReflectionKit.getSuperClassGenericType(type, Mapper.class, 0)); // 清空 Mapper 缓存信息 this.mybatisMapperRegistry.removeMapper(type); this.loadedResources.remove(type.toString()); mapperRegistryCache.remove(mapperType); // 清空 Mapper 方法 mappedStatement 缓存信息 final String typeKey = type.getName() + StringPool.DOT; Set mapperSet = mappedStatements.keySet().stream().filter(ms -> ms.startsWith(typeKey)).collect(Collectors.toSet()); if (!mapperSet.isEmpty()) { mapperSet.forEach(mappedStatements::remove); } } } /** * 使用自己的 MybatisMapperRegistry */ @Override public void addMappers(String packageName, Class superType) { mybatisMapperRegistry.addMappers(packageName, superType); } /** * 使用自己的 MybatisMapperRegistry */ @Override public void addMappers(String packageName) { mybatisMapperRegistry.addMappers(packageName); } /** * 使用自己的 MybatisMapperRegistry */ @Override public T getMapper(Class type, SqlSession sqlSession) { return mybatisMapperRegistry.getMapper(type, sqlSession); } /** * 使用自己的 MybatisMapperRegistry */ @Override public boolean hasMapper(Class type) { return mybatisMapperRegistry.hasMapper(type); } /** * 指定动态SQL生成的默认语言 * * @param driver LanguageDriver */ @Override public void setDefaultScriptingLanguage(Class driver) { if (driver == null) { //todo 替换动态SQL生成的默认语言为自己的。 driver = MybatisXMLLanguageDriver.class; } getLanguageRegistry().setDefaultDriverClass(driver); } @Override public void setDefaultEnumTypeHandler(Class typeHandler) { if (typeHandler != null) { CompositeEnumTypeHandler.setDefaultEnumTypeHandler(typeHandler); } } @Override public void addKeyGenerator(String id, KeyGenerator keyGenerator) { keyGenerators.put(id, keyGenerator); } @Override public Collection getKeyGeneratorNames() { return keyGenerators.keySet(); } @Override public Collection getKeyGenerators() { return keyGenerators.values(); } @Override public KeyGenerator getKeyGenerator(String id) { return keyGenerators.get(id); } @Override public boolean hasKeyGenerator(String id) { return keyGenerators.containsKey(id); } @Override public void addCache(Cache cache) { caches.put(cache.getId(), cache); } @Override public Collection getCacheNames() { return caches.keySet(); } @Override public Collection getCaches() { return caches.values(); } @Override public Cache getCache(String id) { return caches.get(id); } @Override public boolean hasCache(String id) { return caches.containsKey(id); } @Override public void addResultMap(ResultMap rm) { resultMaps.put(rm.getId(), rm); checkLocallyForDiscriminatedNestedResultMaps(rm); checkGloballyForDiscriminatedNestedResultMaps(rm); } @Override public Collection getResultMapNames() { return resultMaps.keySet(); } @Override public Collection getResultMaps() { return resultMaps.values(); } @Override public ResultMap getResultMap(String id) { return resultMaps.get(id); } @Override public boolean hasResultMap(String id) { return resultMaps.containsKey(id); } @Override public void addParameterMap(ParameterMap pm) { parameterMaps.put(pm.getId(), pm); } @Override public Collection getParameterMapNames() { return parameterMaps.keySet(); } @Override public Collection getParameterMaps() { return parameterMaps.values(); } @Override public ParameterMap getParameterMap(String id) { return parameterMaps.get(id); } @Override public boolean hasParameterMap(String id) { return parameterMaps.containsKey(id); } @Override public Map getSqlFragments() { return sqlFragments; } @Override public Collection getMappedStatementNames() { buildAllStatements(); return mappedStatements.keySet(); } @Override public Collection getMappedStatements() { buildAllStatements(); return mappedStatements.values(); } @Override public MappedStatement getMappedStatement(String id) { return this.getMappedStatement(id, true); } @Override public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.get(id); } @Override public boolean hasStatement(String statementName, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.containsKey(statementName); } @Override public Executor newExecutor(Transaction transaction, ExecutorType executorType) { return super.newExecutor(transaction, executorType); } // Slow but a one time cost. A better solution is welcome. @Override protected void checkGloballyForDiscriminatedNestedResultMaps(ResultMap rm) { if (rm.hasNestedResultMaps()) { for (Map.Entry entry : resultMaps.entrySet()) { Object value = entry.getValue(); if (value instanceof ResultMap) { ResultMap entryResultMap = (ResultMap) value; if (!entryResultMap.hasNestedResultMaps() && entryResultMap.getDiscriminator() != null) { Collection discriminatedResultMapNames = entryResultMap.getDiscriminator().getDiscriminatorMap().values(); if (discriminatedResultMapNames.contains(rm.getId())) { entryResultMap.forceNestedResultMaps(); } } } } } } // Slow but a one time cost. A better solution is welcome. @Override protected void checkLocallyForDiscriminatedNestedResultMaps(ResultMap rm) { if (!rm.hasNestedResultMaps() && rm.getDiscriminator() != null) { for (Map.Entry entry : rm.getDiscriminator().getDiscriminatorMap().entrySet()) { String discriminatedResultMapName = entry.getValue(); if (hasResultMap(discriminatedResultMapName)) { ResultMap discriminatedResultMap = resultMaps.get(discriminatedResultMapName); if (discriminatedResultMap.hasNestedResultMaps()) { rm.forceNestedResultMaps(); break; } } } } } protected class StrictMap extends HashMap { private static final long serialVersionUID = -4950446264854982944L; private final String name; private BiFunction conflictMessageProducer; public StrictMap(String name) { super(); this.name = name; } /** * Assign a function for producing a conflict error message when contains value with the same key. *

* function arguments are 1st is saved value and 2nd is target value. * * @param conflictMessageProducer A function for producing a conflict error message * @return a conflict error message * @since 3.5.0 */ public StrictMap conflictMessageProducer(BiFunction conflictMessageProducer) { this.conflictMessageProducer = conflictMessageProducer; return this; } @Override @SuppressWarnings("unchecked") public V put(String key, V value) { if (containsKey(key)) { throw new IllegalArgumentException(name + " already contains value for " + key + (conflictMessageProducer == null ? StringPool.EMPTY : conflictMessageProducer.apply(super.get(key), value))); } if (useGeneratedShortKey) { if (key.contains(StringPool.DOT)) { final String shortKey = getShortName(key); if (super.get(shortKey) == null) { super.put(shortKey, value); } else { super.put(shortKey, (V) new StrictMap.Ambiguity(shortKey)); } } } return super.put(key, value); } @Override public V get(Object key) { V value = super.get(key); if (value == null) { throw new IllegalArgumentException(name + " does not contain value for " + key); } if (useGeneratedShortKey && value instanceof StrictMap.Ambiguity) { throw new IllegalArgumentException(((StrictMap.Ambiguity) value).getSubject() + " is ambiguous in " + name + " (try using the full name including the namespace, or rename one of the entries)"); } return value; } protected class Ambiguity { private final String subject; public Ambiguity(String subject) { this.subject = subject; } public String getSubject() { return subject; } } private String getShortName(String key) { final String[] keyParts = key.split("\\."); return keyParts[keyParts.length - 1]; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy