myBatis源码之Configuration
Configuration类主要是用来存储对mybatis的配置文件及mapper文件解析后的数据,Configuration对象会贯穿整个myabtis的执行流程,为mybatis的执行过程提供必要的配置信息。
/** * @author Clinton Begin */ //mybatis配置文件对应的类,包含了配置项的get set方法,并且有些初始化默认值 public class Configuration { protected Environment environment; /* 是否启用行内嵌套语句**/ protected boolean safeRowBoundsEnabled = false; /* 未找到解释**/ protected boolean safeResultHandlerEnabled = true; /* 是否启用数据组A_column自动映射到Java类中的驼峰命名的属性**/ protected boolean mapUnderscoreToCamelCase = false; /*当对象使用延迟加载时 属性的加载取决于能被引用到的那些延迟属性,否则,按需加载(需要的是时候才去加载)**/ protected boolean aggressiveLazyLoading = true; /*是否允许单条sql 返回多个数据集 (取决于驱动的兼容性) default:true **/ protected boolean multipleResultSetsEnabled = true; /*-允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false**/ protected boolean useGeneratedKeys = false; /* 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。**/ protected boolean useColumnLabel = true; /*配置全局性的cache开关,默认为true**/ protected boolean cacheEnabled = true; /* 在null时也调用 setter,适应于返回Map,3.2版本以上可用**/ protected boolean callSettersOnNulls = false; /* 你打算有一个全局配置打印所有的sql**/ protected String logPrefix; /* 指定 MyBatis 所用日志的具体实现,未指定时将自动查找**/ protected Class <? extends Log> logImpl; /* 设置本地缓存范围,session:就会有数据的共享,statement:语句范围,这样不会有数据的共享**/ protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION; /* 设置但JDBC类型为空时,某些驱动程序 要指定值**/ protected JdbcType jdbcTypeForNull = JdbcType.OTHER; /* 设置触发延迟加载的方法**/ protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" })); /* 设置驱动等待数据响应超时数**/ protected Integer defaultStatementTimeout; /* 设置驱动返回结果数的大小**/ protected Integer defaultFetchSize; /* 执行类型,有simple、resue及batch**/ protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE; /* 指定 MyBatis 如何自动映射 数据基表的列 NONE:不隐射 PARTIAL:部分 FULL:全部**/ protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL; protected Properties variables = new Properties(); protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory(); protected ObjectFactory objectFactory = new DefaultObjectFactory(); protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory(); protected MapperRegistry mapperRegistry = new MapperRegistry(this); /* 是否使用 懒加载 关联对象**/ protected boolean lazyLoadingEnabled = false; /* 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具**/ protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL /* 数据库类型id**/ protected String databaseId; /** * Configuration factory class. * Used to create Configuration for loading deserialized unread properties. * * @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300</a> (google code) */ protected Class<?> configurationFactory; protected final InterceptorChain interceptorChain = new InterceptorChain(); protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(); /* 别名和具体类注册**/ protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry(); protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry(); protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection"); protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection"); protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection"); protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection"); protected final Set<String> loadedResources = new HashSet<String>(); protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers"); protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>(); protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>(); protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>(); protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>(); /* * A map holds cache-ref relationship. The key is the namespace that * references a cache bound to another namespace and the value is the * namespace which the actual cache is bound to. */ protected final Map<String, String> cacheRefMap = new HashMap<String, String>(); public Configuration(Environment environment) { this(); this.environment = environment; } public Configuration() { //通过使用TypeAliasRegistry来注册一些类的别名 typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class); typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class); typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class); typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class); typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class); typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class); typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class); languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class); languageRegistry.register(RawLanguageDriver.class); } public String getLogPrefix() { return logPrefix; } public void setLogPrefix(String logPrefix) { this.logPrefix = logPrefix; } public Class<? extends Log> getLogImpl() { return logImpl; } @SuppressWarnings("unchecked") public void setLogImpl(Class<?> logImpl) { if (logImpl != null) { this.logImpl = (Class<? extends Log>) logImpl; LogFactory.useCustomLogging(this.logImpl); } } public boolean isCallSettersOnNulls() { return callSettersOnNulls; } public void setCallSettersOnNulls(boolean callSettersOnNulls) { this.callSettersOnNulls = callSettersOnNulls; } public String getDatabaseId() { return databaseId; } public void setDatabaseId(String databaseId) { this.databaseId = databaseId; } public Class<?> getConfigurationFactory() { return configurationFactory; } public void setConfigurationFactory(Class<?> configurationFactory) { this.configurationFactory = configurationFactory; } public boolean isSafeResultHandlerEnabled() { return safeResultHandlerEnabled; } public void setSafeResultHandlerEnabled(boolean safeResultHandlerEnabled) { this.safeResultHandlerEnabled = safeResultHandlerEnabled; } public boolean isSafeRowBoundsEnabled() { return safeRowBoundsEnabled; } public void setSafeRowBoundsEnabled(boolean safeRowBoundsEnabled) { this.safeRowBoundsEnabled = safeRowBoundsEnabled; } public boolean isMapUnderscoreToCamelCase() { return mapUnderscoreToCamelCase; } public void setMapUnderscoreToCamelCase(boolean mapUnderscoreToCamelCase) { this.mapUnderscoreToCamelCase = mapUnderscoreToCamelCase; } public void addLoadedResource(String resource) { loadedResources.add(resource); } public boolean isResourceLoaded(String resource) { return loadedResources.contains(resource); } public Environment getEnvironment() { return environment; } public void setEnvironment(Environment environment) { this.environment = environment; } public AutoMappingBehavior getAutoMappingBehavior() { return autoMappingBehavior; } public void setAutoMappingBehavior(AutoMappingBehavior autoMappingBehavior) { this.autoMappingBehavior = autoMappingBehavior; } public boolean isLazyLoadingEnabled() { return lazyLoadingEnabled; } public void setLazyLoadingEnabled(boolean lazyLoadingEnabled) { this.lazyLoadingEnabled = lazyLoadingEnabled; } public ProxyFactory getProxyFactory() { return proxyFactory; } public void setProxyFactory(ProxyFactory proxyFactory) { if (proxyFactory == null) { proxyFactory = new JavassistProxyFactory(); } this.proxyFactory = proxyFactory; } public boolean isAggressiveLazyLoading() { return aggressiveLazyLoading; } public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) { this.aggressiveLazyLoading = aggressiveLazyLoading; } public boolean isMultipleResultSetsEnabled() { return multipleResultSetsEnabled; } public void setMultipleResultSetsEnabled(boolean multipleResultSetsEnabled) { this.multipleResultSetsEnabled = multipleResultSetsEnabled; } public Set<String> getLazyLoadTriggerMethods() { return lazyLoadTriggerMethods; } public void setLazyLoadTriggerMethods(Set<String> lazyLoadTriggerMethods) { this.lazyLoadTriggerMethods = lazyLoadTriggerMethods; } public boolean isUseGeneratedKeys() { return useGeneratedKeys; } public void setUseGeneratedKeys(boolean useGeneratedKeys) { this.useGeneratedKeys = useGeneratedKeys; } public ExecutorType getDefaultExecutorType() { return defaultExecutorType; } public void setDefaultExecutorType(ExecutorType defaultExecutorType) { this.defaultExecutorType = defaultExecutorType; } public boolean isCacheEnabled() { return cacheEnabled; } public void setCacheEnabled(boolean cacheEnabled) { this.cacheEnabled = cacheEnabled; } public Integer getDefaultStatementTimeout() { return defaultStatementTimeout; } public void setDefaultStatementTimeout(Integer defaultStatementTimeout) { this.defaultStatementTimeout = defaultStatementTimeout; } public Integer getDefaultFetchSize() { return defaultFetchSize; } public void setDefaultFetchSize(Integer defaultFetchSize) { this.defaultFetchSize = defaultFetchSize; } public boolean isUseColumnLabel() { return useColumnLabel; } public void setUseColumnLabel(boolean useColumnLabel) { this.useColumnLabel = useColumnLabel; } public LocalCacheScope getLocalCacheScope() { return localCacheScope; } public void setLocalCacheScope(LocalCacheScope localCacheScope) { this.localCacheScope = localCacheScope; } public JdbcType getJdbcTypeForNull() { return jdbcTypeForNull; } public void setJdbcTypeForNull(JdbcType jdbcTypeForNull) { this.jdbcTypeForNull = jdbcTypeForNull; } public Properties getVariables() { return variables; } public void setVariables(Properties variables) { this.variables = variables; } public TypeHandlerRegistry getTypeHandlerRegistry() { return typeHandlerRegistry; } public TypeAliasRegistry getTypeAliasRegistry() { return typeAliasRegistry; } /** * @since 3.2.2 */ public MapperRegistry getMapperRegistry() { return mapperRegistry; } public ReflectorFactory getReflectorFactory() { return reflectorFactory; } public void setReflectorFactory(ReflectorFactory reflectorFactory) { this.reflectorFactory = reflectorFactory; } public ObjectFactory getObjectFactory() { return objectFactory; } public void setObjectFactory(ObjectFactory objectFactory) { this.objectFactory = objectFactory; } public ObjectWrapperFactory getObjectWrapperFactory() { return objectWrapperFactory; } public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) { this.objectWrapperFactory = objectWrapperFactory; } /** * @since 3.2.2 */ public List<Interceptor> getInterceptors() { return interceptorChain.getInterceptors(); } public LanguageDriverRegistry getLanguageRegistry() { return languageRegistry; } public void setDefaultScriptingLanguage(Class<?> driver) { if (driver == null) { driver = XMLLanguageDriver.class; } getLanguageRegistry().setDefaultDriverClass(driver); } public LanguageDriver getDefaultScriptingLanuageInstance() { return languageRegistry.getDefaultDriver(); } public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory); } public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql); parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); return parameterHandler; } public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) { ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds); resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler); return resultSetHandler; } public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); return statementHandler; } public Executor newExecutor(Transaction transaction) { return newExecutor(transaction, defaultExecutorType); } //对应执行器类型(batch、simple、reuse及缓存) public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { //执行批量sql操作 executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { //会重用statement进行sql操作 executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); //执行简单的sql操作,没有什么特别 } if (cacheEnabled) { executor = new CachingExecutor(executor); //如果设置开启cache话会从缓存中查找,如果缓存中没有会查数据库然后将数据放入到缓存中 } executor = (Executor) interceptorChain.pluginAll(executor); //Executor可以被插件拦截 return executor; } public void addKeyGenerator(String id, KeyGenerator keyGenerator) { keyGenerators.put(id, keyGenerator); } public Collection<String> getKeyGeneratorNames() { return keyGenerators.keySet(); } public Collection<KeyGenerator> getKeyGenerators() { return keyGenerators.values(); } public KeyGenerator getKeyGenerator(String id) { return keyGenerators.get(id); } public boolean hasKeyGenerator(String id) { return keyGenerators.containsKey(id); } public void addCache(Cache cache) { caches.put(cache.getId(), cache); } public Collection<String> getCacheNames() { return caches.keySet(); } public Collection<Cache> getCaches() { return caches.values(); } public Cache getCache(String id) { return caches.get(id); } public boolean hasCache(String id) { return caches.containsKey(id); } public void addResultMap(ResultMap rm) { resultMaps.put(rm.getId(), rm); checkLocallyForDiscriminatedNestedResultMaps(rm); checkGloballyForDiscriminatedNestedResultMaps(rm); } public Collection<String> getResultMapNames() { return resultMaps.keySet(); } public Collection<ResultMap> getResultMaps() { return resultMaps.values(); } public ResultMap getResultMap(String id) { return resultMaps.get(id); } public boolean hasResultMap(String id) { return resultMaps.containsKey(id); } public void addParameterMap(ParameterMap pm) { parameterMaps.put(pm.getId(), pm); } public Collection<String> getParameterMapNames() { return parameterMaps.keySet(); } public Collection<ParameterMap> getParameterMaps() { return parameterMaps.values(); } public ParameterMap getParameterMap(String id) { return parameterMaps.get(id); } public boolean hasParameterMap(String id) { return parameterMaps.containsKey(id); } public void addMappedStatement(MappedStatement ms) { mappedStatements.put(ms.getId(), ms); } public Collection<String> getMappedStatementNames() { buildAllStatements(); return mappedStatements.keySet(); } public Collection<MappedStatement> getMappedStatements() { buildAllStatements(); return mappedStatements.values(); } public Collection<XMLStatementBuilder> getIncompleteStatements() { return incompleteStatements; } public void addIncompleteStatement(XMLStatementBuilder incompleteStatement) { incompleteStatements.add(incompleteStatement); } public Collection<CacheRefResolver> getIncompleteCacheRefs() { return incompleteCacheRefs; } public void addIncompleteCacheRef(CacheRefResolver incompleteCacheRef) { incompleteCacheRefs.add(incompleteCacheRef); } public Collection<ResultMapResolver> getIncompleteResultMaps() { return incompleteResultMaps; } public void addIncompleteResultMap(ResultMapResolver resultMapResolver) { incompleteResultMaps.add(resultMapResolver); } public void addIncompleteMethod(MethodResolver builder) { incompleteMethods.add(builder); } public Collection<MethodResolver> getIncompleteMethods() { return incompleteMethods; } public MappedStatement getMappedStatement(String id) { return this.getMappedStatement(id, true); } public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.get(id); } public Map<String, XNode> getSqlFragments() { return sqlFragments; } public void addInterceptor(Interceptor interceptor) { interceptorChain.addInterceptor(interceptor); } public void addMappers(String packageName, Class<?> superType) { mapperRegistry.addMappers(packageName, superType); } public void addMappers(String packageName) { mapperRegistry.addMappers(packageName); } public <T> void addMapper(Class<T> type) { mapperRegistry.addMapper(type); } public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } public boolean hasMapper(Class<?> type) { return mapperRegistry.hasMapper(type); } public boolean hasStatement(String statementName) { return hasStatement(statementName, true); } public boolean hasStatement(String statementName, boolean validateIncompleteStatements) { if (validateIncompleteStatements) { buildAllStatements(); } return mappedStatements.containsKey(statementName); } public void addCacheRef(String namespace, String referencedNamespace) { cacheRefMap.put(namespace, referencedNamespace); } /* * Parses all the unprocessed statement nodes in the cache. It is recommended * to call this method once all the mappers are added as it provides fail-fast * statement validation. */ protected void buildAllStatements() { if (!incompleteResultMaps.isEmpty()) { synchronized (incompleteResultMaps) { // This always throws a BuilderException. incompleteResultMaps.iterator().next().resolve(); } } if (!incompleteCacheRefs.isEmpty()) { synchronized (incompleteCacheRefs) { // This always throws a BuilderException. incompleteCacheRefs.iterator().next().resolveCacheRef(); } } if (!incompleteStatements.isEmpty()) { synchronized (incompleteStatements) { // This always throws a BuilderException. incompleteStatements.iterator().next().parseStatementNode(); } } if (!incompleteMethods.isEmpty()) { synchronized (incompleteMethods) { // This always throws a BuilderException. incompleteMethods.iterator().next().resolve(); } } } /* * Extracts namespace from fully qualified statement id. * * @param statementId * @return namespace or null when id does not contain period. */ protected String extractNamespace(String statementId) { int lastPeriod = statementId.lastIndexOf('.'); return lastPeriod > 0 ? statementId.substring(0, lastPeriod) : null; } // Slow but a one time cost. A better solution is welcome. protected void checkGloballyForDiscriminatedNestedResultMaps(ResultMap rm) { if (rm.hasNestedResultMaps()) { for (Map.Entry<String, ResultMap> entry : resultMaps.entrySet()) { Object value = entry.getValue(); if (value instanceof ResultMap) { ResultMap entryResultMap = (ResultMap) value; if (!entryResultMap.hasNestedResultMaps() && entryResultMap.getDiscriminator() != null) { Collection<String> discriminatedResultMapNames = entryResultMap.getDiscriminator().getDiscriminatorMap().values(); if (discriminatedResultMapNames.contains(rm.getId())) { entryResultMap.forceNestedResultMaps(); } } } } } } // Slow but a one time cost. A better solution is welcome. protected void checkLocallyForDiscriminatedNestedResultMaps(ResultMap rm) { if (!rm.hasNestedResultMaps() && rm.getDiscriminator() != null) { for (Map.Entry<String, String> entry : rm.getDiscriminator().getDiscriminatorMap().entrySet()) { String discriminatedResultMapName = entry.getValue(); if (hasResultMap(discriminatedResultMapName)) { ResultMap discriminatedResultMap = resultMaps.get(discriminatedResultMapName); if (discriminatedResultMap.hasNestedResultMaps()) { rm.forceNestedResultMaps(); break; } } } } } protected static class StrictMap<V> extends HashMap<String, V> { private static final long serialVersionUID = -4950446264854982944L; private String name; public StrictMap(String name, int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); this.name = name; } public StrictMap(String name, int initialCapacity) { super(initialCapacity); this.name = name; } public StrictMap(String name) { super(); this.name = name; } public StrictMap(String name, Map<String, ? extends V> m) { super(m); this.name = name; } @SuppressWarnings("unchecked") public V put(String key, V value) { if (containsKey(key)) { throw new IllegalArgumentException(name + " already contains value for " + key); } if (key.contains(".")) { final String shortKey = getShortName(key); if (super.get(shortKey) == null) { super.put(shortKey, value); } else { super.put(shortKey, (V) new Ambiguity(shortKey)); } } return super.put(key, value); } public V get(Object key) { V value = super.get(key); if (value == null) { throw new IllegalArgumentException(name + " does not contain value for " + key); } if (value instanceof Ambiguity) { throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name + " (try using the full name including the namespace, or rename one of the entries)"); } return value; } private String getShortName(String key) { final String[] keyparts = key.split("\\."); return keyparts[keyparts.length - 1]; } protected static class Ambiguity { private String subject; public Ambiguity(String subject) { this.subject = subject; } public String getSubject() { return subject; } } } }
myBatis源码之Configuration的更多相关文章
- Mybatis 源码分析--Configuration.xml配置文件加载到内存
(补充知识点: 1 byte(字节)=8 bit(位) 通常一个标准英文字母占一个字节位置,一个标准汉字占两个字节位置:字符的例子有:字母.数字系统或标点符号) 1.创建SqlSessionFacto ...
- Mybatis源码解析优秀博文
最近阅读了许久的mybatis源码,小有所悟.同时也发现网上有许多优秀的mybatis源码讲解博文.本人打算把自己阅读过的.觉得不错的一些博文列出来.以此进一步加深对mybatis框架的理解.其实还有 ...
- mybatis源码-解析配置文件(三)之配置文件Configuration解析
目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...
- Mybatis源码解析,一步一步从浅入深(四):将configuration.xml的解析到Configuration对象实例
在Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们看到了XMLConfigBuilder(xml配置解析器)的实例化.而且这个实例化过程在文章:Mybatis源码解析,一步一步从浅 ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- MyBatis源码分析-MyBatis初始化流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析-IDEA新建MyBatis源码工程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...
随机推荐
- [ExtJS5学习笔记]第七节 Extjs5的组件components及其模板事件方法学习
本文地址:http://blog.csdn.net/sushengmiyan/article/details/38487519 本文作者:sushengmiyan ------------------ ...
- 对Bitmap的内存优化
在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图 ...
- shell入门之expr的使用
在expr中加减乘除的使用,脚本如下: #!/bin/sh #a test about expr v1=`expr 5 + 6` echo "$v1" echo `expr 3 + ...
- 安卓AsyncTack详解
我们知道安卓中的UI线程不是线程安全的,即不能在UI线程中进行耗时操作,所以我们通常的做法是开启一个子线程来进行耗时操作,然后将处理后的结果运用Handler机制传递给UI线程,在UI线程中根据处理后 ...
- TortoiseSVN服务器ip地址修改后如何使用
TortoiseSVN是很多人特别是程序员经常使用的工作追述工具,在长期使用过程中难免会遇到服务器迁移ip地址变更的问题.那么在服务器ip地址变化之后,我们要如何继续使用呢?步骤其实非常简单,下面我们 ...
- Ubuntu15.10下如何使用EasyGui模块开发Python GUI
偶然的一个机会,发现了github上的这个开源的项目,easygui for python(一个基于TKinter的模块) 感觉很是惊讶,原来python也可以这么简单的开发出一些GUI界面(究其原因 ...
- 【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42408137 转载请著名出处 本博客相关文档下载 : -- AR ...
- 用SpriteBuilder简化"耕牛遍地走"的动画效果(四)
写到这突然有童鞋质疑,你这哪里是牛,分明是熊嘛! 仔细看了下,还真像牛.反正是这个意思.怪本猫猪牛熊不分,好在道理是一样的. 下面继续,言归正传. 添加一个空白的touchBegan方法,如果没有这个 ...
- IDEA中运行DirectKafkaWordCount程序
1,将SPARK_HOME中的DirectKafkaWordCount程序复制到idea中. 2,由于在KafkaWordCount中已引入相关jar包,此步可略过 3,配置configuration ...
- MySQL 如何使用索引 较为详细的分析和例子
在数据库表中,使用索引可以大大提高查询速度. 假如我们创建了一个 testIndex 表: CREATE TABLE testIndex(i_testID INT NOT NULL,vc_Name V ...