Mybatis源码分析_解析大流程梳理_解析配置文件 (3)

学习mybatis,绕不开一个核心类 Configuration。这个类相当于一个小型数据库,把mybatis里面所有的配置信息基本全部给存储起来了。


package org.apache.ibatis.session;import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.builder.CacheRefResolver;
import org.apache.ibatis.builder.ResultMapResolver;
import org.apache.ibatis.builder.annotation.MethodResolver;
import org.apache.ibatis.builder.xml.XMLStatementBuilder;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.decorators.FifoCache;
import org.apache.ibatis.cache.decorators.LruCache;
import org.apache.ibatis.cache.decorators.SoftCache;
import org.apache.ibatis.cache.decorators.WeakCache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.datasource.jndi.JndiDataSourceFactory;
import org.apache.ibatis.datasource.pooled.PooledDataSourceFactory;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
import org.apache.ibatis.executor.BatchExecutor;
import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ReuseExecutor;
import org.apache.ibatis.executor.SimpleExecutor;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.loader.ProxyFactory;
import org.apache.ibatis.executor.loader.cglib.CglibProxyFactory;
import org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl;
import org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl;
import org.apache.ibatis.logging.log4j.Log4jImpl;
import org.apache.ibatis.logging.log4j2.Log4j2Impl;
import org.apache.ibatis.logging.nologging.NoLoggingImpl;
import org.apache.ibatis.logging.slf4j.Slf4jImpl;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.mapping.BoundSql;
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.mapping.VendorDatabaseIdProvider;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.InterceptorChain;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.LanguageDriverRegistry;
import org.apache.ibatis.scripting.defaults.RawLanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeAliasRegistry;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;/*** @author Clinton Begin*/
public class Configuration {protected Environment environment;/* 是否启用行内嵌套语句**/protected boolean safeRowBoundsEnabled;protected boolean safeResultHandlerEnabled = true;/* 是否启用数据组A_column自动映射到Java类中的驼峰命名的属性**/protected boolean mapUnderscoreToCamelCase;/*当对象使用延迟加载时 属性的加载取决于能被引用到的那些延迟属性,否则,按需加载(需要的是时候才去加载)**/protected boolean aggressiveLazyLoading;/*是否允许单条sql 返回多个数据集  (取决于驱动的兼容性) default:true **/protected boolean multipleResultSetsEnabled = true;/*-允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。  default:false**/protected boolean useGeneratedKeys;/* 使用列标签代替列名。不同的驱动在这方面会有不同的表现, 具体可参考相关驱动文档或通过测试这两种不同的模式来观察所用驱动的结果。**/protected boolean useColumnLabel = true;/*配置全局性的cache开关,默认为true**/protected boolean cacheEnabled = true;protected boolean callSettersOnNulls;protected boolean useActualParamName = true;protected boolean returnInstanceForEmptyRow;/* 日志打印所有的前缀 **/protected String logPrefix;/* 指定 MyBatis 所用日志的具体实现,未指定时将自动查找**/protected Class <? extends Log> logImpl;protected Class <? extends VFS> vfsImpl;/* 设置本地缓存范围,session:就会有数据的共享,statement:语句范围,这样不会有数据的共享**/protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;/* 设置但JDBC类型为空时,某些驱动程序 要指定值**/protected JdbcType jdbcTypeForNull = JdbcType.OTHER;/* 设置触发延迟加载的方法**/protected Set<String> lazyLoadTriggerMethods = new HashSet<>(Arrays.asList("equals", "clone", "hashCode", "toString"));/* 设置驱动等待数据响应超时数**/protected Integer defaultStatementTimeout;/* 设置驱动返回结果数的大小**/protected Integer defaultFetchSize;/* 执行类型,有simple、resue及batch**/protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;/*指定 MyBatis 应如何自动映射列到字段或属性*/protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;protected Properties variables = new Properties();protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();/*MyBatis每次创建结果对象的新实例时,它都会使用对象工厂(ObjectFactory)去构建POJO*/protected ObjectFactory objectFactory = new DefaultObjectFactory();protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();/*延迟加载的全局开关*/protected boolean lazyLoadingEnabled = false;/*指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具*/protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNLprotected 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 (google code)</a>*/protected Class<?> configurationFactory;/*插件集合*/protected final InterceptorChain interceptorChain = new InterceptorChain();/*TypeHandler注册中心*/protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();/*TypeAlias注册中心*/protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();//-------------------------------------------------------------/*mapper接口的动态代理注册中心*/protected final MapperRegistry mapperRegistry = new MapperRegistry(this);/*mapper文件中增删改查操作的注册中心*/protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection");/*mapper文件中配置cache节点的 二级缓存*/protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");/*mapper文件中配置的所有resultMap对象  key为命名空间+ID*/protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");/*mapper文件中配置KeyGenerator的insert和update节点,key为命名空间+ID*/protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<>("Key Generators collection");/*加载到的所有*mapper.xml文件*/protected final Set<String> loadedResources = new HashSet<>();/*mapper文件中配置的sql元素,key为命名空间+ID*/protected final Map<String, XNode> sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers");protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<>();protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<>();protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<>();protected final Collection<MethodResolver> incompleteMethods = new LinkedList<>();/** 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<>();public Configuration(Environment environment) {this();this.environment = environment;}public Configuration() {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);}以下代码省略}

 这里,我先介绍介个比较重要的变量:

typeAliasRegistry  : 存放我们自定义的接口的别名
mapperRegistry  : 存放包装了我们业务接口的动态代理类
mappedStatements : 增、删、改、查语句的包装类,即注册中心
resultMaps  : resultMap返回值类型
loadedResources : 存放我们加载到的所有*mapper.xml文件
sqlFragments : mapper文件中配置的sql元素,key为命名空间+ID
objectFactory : MyBatis每次创建结果对象的新实例时,它都会使用对象工厂(ObjectFactory)去构建POJO
lazyLoadingEnabled : 延迟加载的全局开关
proxyFactory : 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具

先介绍这么多,剩下的用到的时候再介绍。下面再来看一张图形:

XMLConfigBuilder :负责解析mybatis配置的全局信息。包括数据源、数据库连接池、是否懒加载、类的别名信息等等

XMLMapperBuilder :负责解析具体的***Mapper.xml文件。比如里面的resultMap、sql、缓存等信息

XMLStatementBuilder :负责解析***Mapper.xml文件中的 增、删、改、查等信息

MapperBuilderAssistant :助手类,负责对 XMLMapperBuilder 和 XMLStatementBuilder中创建对象提供帮助。说白了就是上面2个负责解析、而MapperBuilderAssistant负责把解析的内容封装成对象。

而以上这些类解析的信息,全部会存放到Configuration类中。Configuration类是应用级的生命周期,只要mybatis不停,它就会一直纯在而且是全局唯一的,不存在多实例的情况。

源码分析:

1. 首先定义一个mybatis的全局文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="db.properties"/><settings><!-- 设置自动驼峰转换		 --><setting name="mapUnderscoreToCamelCase" value="true" /><!-- 开启二级缓存(默认是开的,这里写出来是为了方便代码维护) --><!-- <setting name="cacheEnabled" value="true" />  --><!-- 开启懒加载 -->		<!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。默认:true --><setting name="aggressiveLazyLoading" value="false" /></settings><!-- 别名定义 --><typeAliases><package name="com.enjoylearning.mybatis.entity" /></typeAliases><plugins><plugin interceptor="com.enjoylearning.mybatis.Interceptors.ThresholdInterceptor"> <property name="threshold" value="10"/></plugin><!--  		 <plugin interceptor="com.github.pagehelper.PageInterceptor"><property name="pageSizeZero" value="true" /></plugin> --></plugins><!--配置environment环境 --><environments default="development"><!-- 环境配置1,每个SqlSessionFactory对应一个环境 --><environment id="development"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="${jdbc_driver}" /><property name="url" value="${jdbc_url}" /><property name="username" value="${jdbc_username}" /><property name="password" value="${jdbc_password}" /></dataSource></environment></environments><!-- 映射文件,mapper的配置文件 --><mappers><!--直接映射到相应的mapper文件 --><mapper resource="sqlmapper/TUserMapper.xml"/><!--<mapper resource="sqlmapper/TUserTestMapper.xml" /><mapper resource="sqlmapper/TRoleMapper.xml" /><mapper resource="sqlmapper/TJobHistoryMapper.xml" /><mapper resource="sqlmapper/TPositionMapper.xml" /><mapper resource="sqlmapper/THealthReportFemaleMapper.xml" /><mapper resource="sqlmapper/THealthReportMaleMapper.xml" />--></mappers></configuration>  

2. 定义一个接口和一个对应的xml文件

package com.enjoylearning.mybatis.mapper;import java.util.List;
import java.util.Map;import org.apache.ibatis.annotations.Param;import com.enjoylearning.mybatis.entity.EmailSexBean;
import com.enjoylearning.mybatis.entity.TJobHistory;
import com.enjoylearning.mybatis.entity.TUser;public interface TUserMapper {TUser selectByPrimaryKey(Integer id);List<TUser> selectAll();List<TUser> selectTestResultMap();List<TUser> selectAllTest();int deleteByPrimaryKey(Integer id);int insert1(TUser record);int insert2(TUser record);int insertSelective(TUser record);int updateByPrimaryKeySelective(TUser record);int updateByPrimaryKey(TUser record);List<TUser> selectUserPosition1();List<TUser> selectUserPosition2();List<TUser> selectUserJobs1();List<TUser> selectUserJobs2();List<TUser> selectUserHealthReport();List<TUser> selectUserRole();List<TUser> selectByEmailAndSex1(Map<String, Object> param);List<TUser> selectByEmailAndSex2(@Param("email")String email,@Param("sex")Byte sex);List<TUser> selectByEmailAndSex3(EmailSexBean esb);List<TUser> selectBySymbol(@Param("tableName")String tableName,@Param("inCol")String inCol,@Param("orderStr")String orderStr,@Param("userName")String userName);List<TUser> selectIfOper(@Param("email")String email,@Param("sex")Byte sex);List<TUser> selectIfandWhereOper(@Param("email")String email,@Param("sex")Byte sex);List<TUser> selectChooseOper(@Param("email")String email,@Param("sex")Byte sex);int updateIfOper(TUser record);int updateIfAndSetOper(TUser record);int insertIfOper(TUser record);List<TUser> selectForeach4In(String[] names);int insertForeach4Batch(List<TUser> users);}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.enjoylearning.mybatis.mapper.TUserMapper"><!--开启二级缓存,需要配置2次,级别仅限于当前namespace--><!--<cache></cache>--><select id="selectByPrimaryKey" resultType="TUser" >selectid, userName, realName, sex, mobile, email, notefrom t_userwhere id = #{id,jdbcType=INTEGER}</select><select id="selectAll" resultType="TUser">selectid, userName, realName, sex, mobile, email, notefrom t_user</select><resultMap id="UserResultMap" type="TUser" autoMapping="true"><id column="id" property="id" /><result column="userName" property="userName" /><result column="realName" property="realName" /><result column="sex" property="sex" /><result column="mobile" property="mobile" /><result column="email" property="email" /><result column="note" property="note" /><association property="position" javaType="TPosition" columnPrefix="post_"><id column="id" property="id"/><result column="name" property="postName"/><result column="note" property="note"/></association></resultMap><select  id="selectTestResultMap" resultMap="UserResultMap" >selecta.id,userName,realName,sex,mobile,email,a.note,b.id  post_id,b.post_name,b.note post_notefrom t_user a,t_position bwhere a.position_id = b.id</select><!--  	<cache></cache> --><resultMap id="BaseResultMap" type="TUser"><!-- <constructor> <idArg column="id" javaType="int"/> <arg column="userName"javaType="String"/> </constructor> --><id column="id" property="id" /><result column="userName" property="userName" /><result column="realName" property="realName" /><result column="sex" property="sex" /><result column="mobile" property="mobile" /><result column="email" property="email" /><result column="note" property="note" /></resultMap><sql id="Base_Column_List">id, userName, realName, sex, mobile, email, note,position_id</sql><resultMap id="userAndPosition1" extends="BaseResultMap" type="TUser"><association property="position" javaType="TPosition" columnPrefix="post_" ><id column="id" property="id"/><result column="name" property="postName"/><result column="note" property="note"/></association></resultMap><resultMap id="userAndPosition2" extends="BaseResultMap" type="TUser"><association property="position" fetchType="lazy"  column="position_id" select="com.enjoylearning.mybatis.mapper.TPositionMapper.selectByPrimaryKey" /></resultMap><select id="selectUserPosition1" resultMap="userAndPosition1"  >selecta.id,userName,realName,sex,mobile,email,a.note,b.id post_id,b.post_name,b.note post_notefrom t_user a,t_position bwhere a.position_id = b.id</select><select id="selectUserPosition2" resultMap="userAndPosition2" >selecta.id,a.userName,a.realName,a.sex,a.mobile,a.position_idfrom t_user a</select><resultMap id="userAndJobs1" extends="BaseResultMap" type="TUser"><collection property="jobs"ofType="com.enjoylearning.mybatis.entity.TJobHistory" ><result column="comp_name" property="compName" jdbcType="VARCHAR" /><result column="years" property="years" jdbcType="INTEGER" /><result column="title" property="title" jdbcType="VARCHAR" /></collection></resultMap><resultMap id="userAndJobs2" extends="BaseResultMap" type="TUser"><collection property="jobs" fetchType="lazy" column="id"select="com.enjoylearning.mybatis.mapper.TJobHistoryMapper.selectByUserId" /></resultMap><select id="selectUserJobs1" resultMap="userAndJobs1">selecta.id,a.userName,a.realName,a.sex,a.mobile,b.comp_name,b.years,b.titlefrom t_user a,t_job_history bwhere a.id = b.user_id</select><select id="selectUserJobs2" resultMap="userAndJobs2">selecta.id,a.userName,a.realName,a.sex,a.mobilefrom t_user a</select><resultMap id="userAndHealthReportMale" extends="userAndHealthReport" type="TUser"><collection property="healthReports" column="id"select= "com.enjoylearning.mybatis.mapper.THealthReportMaleMapper.selectByUserId"></collection></resultMap><resultMap id="userAndHealthReportFemale" extends="userAndHealthReport" type="TUser"><collection property="healthReports" column="id"select= "com.enjoylearning.mybatis.mapper.THealthReportFemaleMapper.selectByUserId"></collection></resultMap><resultMap id="userAndHealthReport" extends="BaseResultMap" type="TUser"><discriminator column="sex"  javaType="int"><case value="1" resultMap="userAndHealthReportMale"/><case value="2" resultMap="userAndHealthReportFemale"/></discriminator></resultMap><select id="selectUserHealthReport" resultMap="userAndHealthReport">select<include refid="Base_Column_List" />from t_user a</select><resultMap type="TUser" id="userRoleInfo" extends="BaseResultMap"><collection property="roles" ofType="TRole" columnPrefix="role_"><result column="id" property="id" /><result column="Name" property="roleName" /><result column="note" property="note" /></collection></resultMap><select id="selectUserRole" resultMap="userRoleInfo">select a.id,a.userName,a.realName,a.sex,a.mobile,a.note,b.role_id,c.role_name,c.note role_notefrom t_user a,t_user_role b,t_role cwhere a.id = b.user_id ANDb.role_id = c.id</select><select id="selectUserByRoleId" resultMap="userRoleInfo">select<include refid="Base_Column_List" />from t_user a,t_user_role bwhere a.id = b.user_id andb.role_id = #{id}</select><!--可读性差,杜绝使用--><select id="selectByEmailAndSex1" resultMap="BaseResultMap"		parameterType="map">select<include refid="Base_Column_List" />from t_user awhere a.email like CONCAT('%', #{email}, '%') anda.sex =#{sex}</select><!--注解的方式传递。参数少于5个,推荐使用--><select id="selectByEmailAndSex2" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_user awhere a.email like CONCAT('%', #{email}, '%') anda.sex =	#{sex}</select><!-- POJO的方式传递参数--><select id="selectByEmailAndSex3" resultMap="BaseResultMap"parameterType="com.enjoylearning.mybatis.entity.EmailSexBean">select<include refid="Base_Column_List" />from t_user awhere a.email like CONCAT('%', #{email}, '%') anda.sex =	#{sex}</select><select id="selectBySymbol" resultMap="BaseResultMap">select${inCol}from ${tableName} awhere a.userName = #{userName}order by ${orderStr}</select><select id="selectIfOper" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_user awhere   1=1<if test="email != null and email != ''">and a.email like CONCAT('%', #{email}, '%')</if><if test="sex != null ">and a.sex = #{sex}</if></select><select id="selectIfandWhereOper" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_user a<where><if test="email != null and email != ''">and a.email like CONCAT('%', #{email}, '%')</if><if test="sex != null ">and a.sex = #{sex}</if></where></select><select id="selectChooseOper" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_user a<where><choose><when test="email != null and email != ''">and a.email like CONCAT('%', #{email}, '%')</when><when test="sex != null">and a.sex = #{sex}</when><otherwise>and 1=1</otherwise></choose></where></select><update id="updateIfOper" parameterType="TUser">update t_userset<if test="userName != null">userName = #{userName,jdbcType=VARCHAR},</if><if test="realName != null">realName = #{realName,jdbcType=VARCHAR},</if><if test="sex != null">sex = #{sex,jdbcType=TINYINT},</if><if test="mobile != null">mobile = #{mobile,jdbcType=VARCHAR},</if><if test="email != null">email = #{email,jdbcType=VARCHAR},</if><if test="note != null">note = #{note,jdbcType=VARCHAR}</if>where id = #{id,jdbcType=INTEGER}</update><update id="updateIfAndSetOper" parameterType="TUser">update t_user<set><if test="userName != null">userName = #{userName,jdbcType=VARCHAR},</if><if test="realName != null">realName = #{realName,jdbcType=VARCHAR},</if><if test="sex != null">sex = #{sex,jdbcType=TINYINT},</if><if test="mobile != null">mobile = #{mobile,jdbcType=VARCHAR},</if><if test="email != null">email = #{email,jdbcType=VARCHAR},</if><if test="note != null">note = #{note,jdbcType=VARCHAR},</if></set>where id = #{id,jdbcType=INTEGER}</update><insert id="insertIfOper" parameterType="TUser">insert into t_user (<if test="id != null">id,</if><if test="userName != null">userName,</if><if test="realName != null">realName,</if><if test="sex != null">sex,</if><if test="mobile != null">mobile,</if><if test="email != null">email,</if><if test="note != null">note</if>)values(<if test="id != null">#{id,jdbcType=INTEGER},</if><if test="userName != null">#{userName,jdbcType=VARCHAR},</if><if test="realName != null">#{realName,jdbcType=VARCHAR},</if><if test="sex != null">#{sex,jdbcType=TINYINT},</if><if test="mobile != null">#{mobile,jdbcType=VARCHAR},</if><if test="email != null">#{email,jdbcType=VARCHAR},</if><if test="note != null">#{note,jdbcType=VARCHAR}</if>)</insert><select id="selectForeach4In" resultMap="BaseResultMap">select<include refid="Base_Column_List" />from t_user awhere a.userName in<foreach collection="array" open="(" close=")" item="userName" separator=",">#{userName}</foreach></select><insert id="insertForeach4Batch" useGeneratedKeys="true"		keyProperty="id">insert into t_user (userName, realName,sex, mobile,email,note,position_id)values<foreach collection="list" separator="," item="user">(#{user.userName,jdbcType=VARCHAR},#{user.realName,jdbcType=VARCHAR},#{user.sex,jdbcType=TINYINT},#{user.mobile,jdbcType=VARCHAR},#{user.email,jdbcType=VARCHAR},#{user.note,jdbcType=VARCHAR},#{user.position.id,jdbcType=INTEGER})</foreach></insert><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">delete from t_userwhere id = #{id,jdbcType=INTEGER}</delete><insert id="insert1" parameterType="TUser" useGeneratedKeys="true"	keyProperty="id">insert into t_user (id, userName, realName,sex, mobile,email,note, position_id)values (#{id,jdbcType=INTEGER},#{userName,jdbcType=VARCHAR},#{realName,jdbcType=VARCHAR},#{sex,jdbcType=TINYINT}, #{mobile,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{note,jdbcType=VARCHAR},#{position.id,jdbcType=INTEGER})</insert><insert id="insert2" parameterType="TUser"><!-- MySql配置after  Oracle配置为before --><!-- select SEQ_ID.nextval from dual--><selectKey keyProperty="id" order="AFTER" resultType="int">selectLAST_INSERT_ID()</selectKey>insert into t_user (id, userName, realName,sex, mobile,email,note,position_id)values (#{id,jdbcType=INTEGER},#{userName,jdbcType=VARCHAR},#{realName,jdbcType=VARCHAR},#{sex,jdbcType=TINYINT}, #{mobile,jdbcType=VARCHAR},#{email,jdbcType=VARCHAR},#{note,jdbcType=VARCHAR},#{position.id,jdbcType=INTEGER})</insert><insert id="insertSelective" parameterType="TUser" useGeneratedKeys="true"		keyProperty="id">insert into t_user<trim prefix="(" suffix=")" suffixOverrides="," ><if test="id != null">id,</if><if test="userName != null">userName,</if><if test="realName != null">realName,</if><if test="sex != null">sex,</if><if test="mobile != null">mobile,</if><if test="email != null">email,</if><if test="note != null">note,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="id != null">#{id,jdbcType=INTEGER},</if><if test="userName != null">#{userName,jdbcType=VARCHAR},</if><if test="realName != null">#{realName,jdbcType=VARCHAR},</if><if test="sex != null">#{sex,jdbcType=TINYINT},</if><if test="mobile != null">#{mobile,jdbcType=VARCHAR},</if><if test="email != null">#{email,jdbcType=VARCHAR},</if><if test="note != null">#{note,jdbcType=VARCHAR},</if></trim></insert><update id="updateByPrimaryKeySelective" parameterType="TUser">update t_user<set><if test="userName != null">userName = #{userName,jdbcType=VARCHAR},</if><if test="realName != null">realName = #{realName,jdbcType=VARCHAR},</if><if test="sex != null">sex = #{sex,jdbcType=TINYINT},</if><if test="mobile != null">mobile = #{mobile,jdbcType=VARCHAR},</if><if test="email != null">email = #{email,jdbcType=VARCHAR},</if><if test="note != null">note = #{note,jdbcType=VARCHAR},</if><if test="position != null">position_id = #{position.id,jdbcType=INTEGER},</if></set>where id = #{id,jdbcType=INTEGER}</update><update id="updateByPrimaryKey" parameterType="TUser">update t_usersetuserName = #{userName,jdbcType=VARCHAR},realName =#{realName,jdbcType=VARCHAR},sex = #{sex,jdbcType=TINYINT},mobile =#{mobile,jdbcType=VARCHAR},email = #{email,jdbcType=VARCHAR},note =#{note,jdbcType=VARCHAR},position_id = #{position.id,jdbcType=INTEGER}where id = #{id,jdbcType=INTEGER}</update>
</mapper>

3、开启测试类

4. 其实,我们就是创建了一个 SqlSessionFactory 工厂类而已,它是负责生产SqlSession对象的。而SqlSession是连接数据库的核心类。但是,在创建SqlSessionFactory之前,我们还生成了一个XMLConfigBuilder对象,并且调用了parse方法进行mybatis整个配置信息的解析。

XMLConfigBuilder 负责解析mybatis的全局配置信息。

1. 进入parse方法中,我们发现它解析的开始标签为  "/configuration".  而这个正是我们mybatis全局信息的根节点

 

2. 进一步查看, 其实逻辑很简单。就是根据每个标签进行逐个解析然后封装到Configuration对象中。

3. 这里我们重点说一下 mapperElement方法,它就是单独解析我们自己写sql语句的xml文件的。也就是说,我们使用mybatis写的增删改查语句是放在特定的xml文件中的,而这个方法就是专门解析我们业务sql的。

 此时,我们就引出了 XMLMapperBuilder 对象了。

configurationElement方法就是负责解析具体的业务xml的,就是解析咱们的sql信息的。configuration.addLoadedResource(resource) 就会解析完以后,把当前的xml放入loadedResources变量中

 bindMapperForNamespace 就是把当前的接口信息绑定到Configuration对象的mapperRegistry变量中。

4. 全部解析完以后,生成一个SqlSessionFactory工厂对象,这个工厂持有Configuration对象。最终返回。

 

到现在为止,一个大的解析就结束了。但是,里面还有很多的细节值得返回研究。比如ResultMap是如何解析与封装的、 sql的增删改查是如何封装的、 好了缓存。太多重要的信息了。下一篇继续对这些比较重要的细节进行分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/459.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+VueCli+TS官方模板简析

使用脚手架安装相关依赖 使用vueCli 安装预设的vuextslessrouter ## 查看vue/cli版本&#xff0c;确保vue/cli版本在4.5.0以上 vue --version## 安装或者升级你的vue/cli npm install -g vue/cli## 创建 vue create vue3_cli_ts_htgl //create vue3_cli_ts_htgl为自…

ELFK日志分析系统并使用Filter对日志数据进行处理

系列文章目录 文章目录 系列文章目录一、FilebeatELK1.FilebeatELK 部署2.Filebeat 节点上操作 二、Filter1.内置正则表达式调用 总结 一、FilebeatELK 1.FilebeatELK 部署 Node1节点&#xff08;2C/4G&#xff09;&#xff1a;node1/192.168.169.10 Elasticsearch Node2节点…

深入浅出之Docker Compose详解

目录 1.Docker Compose概述 1.1 Docker Compose 定义 1.2 Docker Compose产生背景 1.3 Docker Compose 核心概念 1.4 Docker Compose 使用步骤 1.5 Docker Compose 常用命令 2. Docker Compose 实战 2.1 Docker Compose下载和卸载 2.2 Docker Compose 项目概述 2.3 Do…

从0到1搭建spring cloud alibaba +springboot+nacos+dubbo微服务

版本关系&#xff1a; spring cloud alibaba各组件对应关系 创建父工程&#xff0c;pom.xml配置如下&#xff1a; 由以上版本对应关系&#xff1a; springboot版本&#xff1a;2.3.2.RELEASE spring cloud 版本选择&#xff1a;Hoxton.SR9 spring cloud alibaba版本选择&#…

Elasticsearch:增量快照如何工作?

作者&#xff1a;Lutf ur Rehman Elastic 提供许多由讲师指导的面对面和虚拟现场培训以及点播培训。 我们的旗舰课程是 Elasticsearch 工程师、Kibana 数据分析和 Elastic 可观测性工程师。 所有这些课程都会获得认证。如果你想更多了解这些认证方面的知识&#xff0c;请阅读文…

5-NumPy如何创建N维数组?【视频版】

目录 问题视频解答 问题 视频解答 点击观看&#xff1a; 5-如何创建等N维数组&#xff1f;

大佬详细讲解:银行核心项目之测试阶段

最近有小伙伴留言说「想了解核心系统建设中&#xff0c;冒烟、SIT、UAT、回归测试的重点&#xff0c;如何设计测试案例&#xff0c;或相关的资料推荐等」。 这个话题很笼统&#xff0c;测试这一块儿除了业务测试&#xff0c;还有性能测试、安全测试等&#xff1b;以及不同的角…

本地Linux 部署 Dashy 并远程访问

文章目录 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 转载自cpolar极点云文章&#xff1a;本地Linux 部署 Dashy 并远程访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你…

Sequential用法

目录 1.官方文档解释 1.1原文参照 1.2中文解释 2.参考代码 3.一些参考使用 3.1生成网络 3.2 感知机的实现 3.3组装网络层 1.官方文档解释 1.1原文参照 A sequential container. Modules will be added to it in the order they are passed in the constructor. A…

OJ# 376 机器翻译

题目描述 ​ 小李的电脑上安装了一个机器翻译软件&#xff0c;他经常用这个软件来翻译英语文章。 ​这个翻译软件的原理很简单&#xff0c;它只是从头到尾&#xff0c;依次将每个英文单词用对应的中文含义来替换。对于每个英文单词&#xff0c;软件会先在内存中查找这个单词的…

【账号篇】华硕电脑-华硕账号注销教程

【账号篇】华硕电脑-华硕账号注销教程 手机号和邮箱号注册的华硕账户无法合并&#xff0c;无法互相关联&#xff0c;需要数据同步的可以选择先注销删除其中一个账号再关联—【蘇小沐】 文章目录 【账号篇】华硕电脑-华硕账号注销教程1.实验环境 &#xff08;一&#xff09;华硕…

CPU上下文切换原理剖析

CPU上下文 CPU上下文其实是一些环境正是有这些环境的支撑&#xff0c;任务得以运行&#xff0c;而这些环境的硬件条件便是CPU寄存器和程序计数器。CPU寄存器是CPU内置的容量非常小但是速度极快的存储设备&#xff0c;程序计数器则是CPU在运行任何任务时必要的&#xff0c;里面…