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

news2024/11/7 20:53:54

学习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 OGNL

  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 (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" >
		select
		id, userName, realName, sex, mobile, email, note
		from t_user
		where id = #{id,jdbcType=INTEGER}
	</select>



    <select id="selectAll" resultType="TUser">
		select
		id, userName, realName, sex, mobile, email, note
		from 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" >
		select
		    a.id,
		    userName,
			realName,
			sex,
			mobile,
			email,
			a.note,
			b.id  post_id,
			b.post_name,
			b.note post_note
		from t_user a,
			t_position b
		where 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"  >
		select
		    a.id,
		    userName,
			realName,
			sex,
			mobile,
			email,
			a.note,
			b.id post_id,
			b.post_name,
			b.note post_note
		from t_user a,
			t_position b
		where a.position_id = b.id

	</select>

    <select id="selectUserPosition2" resultMap="userAndPosition2" >
		select
		a.id,
		a.userName,
		a.realName,
		a.sex,
		a.mobile,
		a.position_id
		from 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">
		select
		a.id,
		a.userName,
		a.realName,
		a.sex,
		a.mobile,
		b.comp_name,
		b.years,
		b.title
		from t_user a,
		t_job_history b
		where a.id = b.user_id

	</select>

    <select id="selectUserJobs2" resultMap="userAndJobs2">
		select
		a.id,
		a.userName,
		a.realName,
		a.sex,
		a.mobile
		from 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_note
		from t_user a,
		     t_user_role b,
		     t_role c
		where a.id = b.user_id AND
		      b.role_id = c.id
     </select>


    <select id="selectUserByRoleId" resultMap="userRoleInfo">
        select
        <include refid="Base_Column_List" />
        from t_user a,
        t_user_role b
        where a.id = b.user_id and
        b.role_id = #{id}
    </select>

    <!--可读性差,杜绝使用-->
    <select id="selectByEmailAndSex1" resultMap="BaseResultMap"		parameterType="map">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex =#{sex}
    </select>

    <!--注解的方式传递。参数少于5个,推荐使用-->
    <select id="selectByEmailAndSex2" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex =	#{sex}
    </select>

    <!-- POJO的方式传递参数-->
    <select id="selectByEmailAndSex3" resultMap="BaseResultMap"
            parameterType="com.enjoylearning.mybatis.entity.EmailSexBean">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where a.email like CONCAT('%', #{email}, '%') and
        a.sex =	#{sex}
    </select>


    <select id="selectBySymbol" resultMap="BaseResultMap">
		select
		${inCol}
		from ${tableName} a
		where a.userName = #{userName}
		order by ${orderStr}
	</select>



    <select id="selectIfOper" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from t_user a
        where   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_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>
        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 a
        where 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_user
		where 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">
            select
            LAST_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_user
		set
		userName = #{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写的增删改查语句是放在特定的xmk文件中的,而这个方法就是专门解析我们业务sql的。

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

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

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

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

 

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见的网络抓包工具推荐

因为发现好多人想抓包&#xff0c;但是不知道有哪些工具&#xff0c;今天我给大家推荐几款抓包工具&#xff0c;希望对大家有所帮助。 网络抓包工具的用途 网络抓包工具的主要功能是将网络执行的过程&#xff0c;详细的记录下来。如果你是一个程序员&#xff0c;肯定对网络抓…

上传视频文件,基于断点续传(整合Minio)

目录 1、什么是断点续传 2、分块文件 3、合并文件 4、 Minio 分布式文件系统整合断点续传 4.1 进行文件分块上传到 Minio 4.2 进行 Minio 中分块文件的合并 5、使用 Minio 进行断点续传的注意事项 相信很多小伙伴在上传下载图片或者视频的时候&#xff0c;突然间&#xff08;…

java多商户商城系统源码下载支持二开

商城系统源码 整套源码开源 支持二次开发&#xff0c;支持PHP商城源码及JAVA商城源码 多端应用&#xff0c;一键部署,满足多场景业务需求 支持商城APP源码、分销商城源码、B2B2C源码、B2B网上商城源码等等 社交电商引流&#xff0c;数十种促销工具&#xff0c;帮助提升店铺成…

ncnn源码阅读(一)----阅读方法和参考教程

〇、ncnn源码阅读的方法和参考教程 目前我的工作涉及推理框架较多&#xff0c;所以就想阅读一些他人的开源框架&#xff0c;来提升自己在语言层面和框架层面的认知。这个过程中发现了一些比较好的教程&#xff0c;我的阅读ncnn源码之旅将参考 嘻嘻嘻大佬。 一、从下载代码开始…

ThreadPoolExecutor的execute方法

方法介绍 execute方法是将任务提交到线程池中的核心方法。线程池的执行流程可以通过execute内部进行的逻辑判断得知。 代码展示与分析 Runnable command。方法体中的参数代表着提交过来的任务。任务不能为null的非空判断。不然就会抛出空指针异常。int c ctl.get();获取ctl的…

【性能测试二】性能测试工具LoadRunner学习一 VUG

目录 &#x1f31f;一、LoadRunner的环境搭建 &#x1f31f;二、介绍LoadRunner &#x1f31f;三、LoadRunner脚本录制&#xff08;重点&#xff09; &#x1f308;1、介绍一个WebTours项目 &#x1f308;2、脚本录制 &#x1f308;3、脚本加强&#xff08;重点&#xff…

【kubernetes系列】Kubernetes中的重要概念(二)

本章节将继续分享关于kubernetes中的一些重要概念。 一、Pod Pod 是 Kubernetes 的最小工作单元。每个 Pod 包含一个或多个容器。Pod 中的容器会作为一个整体被 Master 调度到某个 Node 上运行。(可以把pod想象成豌豆荚&#xff0c;里面的豌豆就是容器&#xff0c;可以有一个或…

浅析电动机综合保护器的工作原理与应用 安科瑞 许敏

摘 要&#xff1a;电动机综合保护器以先进技术为支持&#xff0c;具有非常强大的整机功能&#xff0c;就实际应用效果来说&#xff0c;其测试精度、分辨率较高&#xff0c;具有良好的抗干扰能力&#xff0c;保护动作可靠&#xff0c;能为电动机提供负荷保护、短路保护、断相保…

《面试1v1》MyBatis

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

Redis使用Bitmap实现数据统计

一、概念 什么是二值状态?二值状态就是元素只有0和1这两种情况&#xff0c;比如在签到的场景中只有签到和未签到两种&#xff0c;或者登陆的场景中只有已登录和未登录的情况。 Bitmap 的底层数据结构用的是 String 类型的 SDS 数据结构来保存位数组&#xff0c;Redis 把每个…

2-css-2

一 复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 作用&#xff1a;更准确、更高效的选择目标元素&#xff08;标签&#xff09;。 1 后代选择器 后代选择器&#xff1a;选中某元素的后代元素。 选择器写法&#xff1a;父选择器…

05_Linux设备树下的LED驱动

目录 设备树LED驱动原理 修改设备树文件 LED灯驱动程序编写 编写测试APP 运行测试 设备树LED驱动原理 驱动文件中定义有关寄存器物理地址,然后使用io_remap函数进行内存映射,得到对应的虚拟地址,最后操作寄存器对应的虚拟地址完成对GPIO的初始化。本实验使用设备树来向 L…

操作系统——Windows 进程管理

一、实验题目 Windows 进程管理 二、实验目的 &#xff08;1&#xff09;学会使用 VC 编写基本的 Win32 Consol Application&#xff08;控制台应用程序)。 &#xff08;2&#xff09;通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作&#xff0c;进一步熟…

UEditorPlus v3.2.0 兼容规则过滤,若干问题修复

UEditor 是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于 MIT 开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;…

绩效管理怎么做?一文带你搞懂绩效管理!

在职场中&#xff0c;我们经常会听到“绩效管理”这个词汇。但是&#xff0c;你是否真正理解绩效管理的含义和意义呢&#xff1f; 现在很多企业的绩效管理都变味了&#xff0c;让员工觉得绩效就是想方设法扣工资、绩效就是控制人的手段、绩效不是激励而是威胁、绩效就是打分游…

41 # 编码的问题

常见的进制 10 进制&#xff1a;除表示正负的符号外&#xff0c;以 1~9 开头&#xff0c;由 0~9 组成。如 128&#xff0c;234&#xff0c;-278。2 进制&#xff1a;以 0b 开头&#xff0c;0b118 进制&#xff1a;以 0 或 0o开头&#xff0c;由 0~7 组成的数。如 0126, 050000…

【Redis】多级缓存之OpenResty:nginx查询Tomcat与Redis以及nginx本地缓存

目录 一、认识OpenResty 二、请求参数处理 三、查询Tomcat 四、Redis缓存预热 五、查询Redis缓存 六、nginx本地缓存 一、认识OpenResty OpenResty是一个基于nginx的高性能Web平台&#xff0c;他用于方便的搭建能够处理高并发、扩展性极高的动态Web应用、Web服务和动态网…

SuperMap GIS基础产品组件GIS FAQ集锦(3)

SuperMap GIS基础产品组件GIS FAQ集锦&#xff08;3&#xff09; 【Unity】Unity中如何将场景内容限制在屏幕中间1/3处&#xff1f; 【解决办法】1、新建两个相机&#xff0c;一个代表左边屏幕&#xff0c;一个代表右边屏幕 2、通过Viewport Rect设置相机显示在屏幕中的位置&a…

南卡OE Pro首销售罄,发烧友称其为开放式耳机旗舰标杆!

6月19日南卡官博放出消息&#xff0c;南卡旗下的开放式旗舰机型OE Pro首销售罄&#xff0c;开启预售&#xff0c;将在24日早上10点整再次现货发售&#xff0c;不难看出这款开放式耳机非常火爆&#xff0c;非常受欢迎&#xff0c;被广大发烧友们誉为开放式耳机的旗舰标杆&#x…

会 java 8 stream流就会大数据!

如果你会任意一门语言的stream流&#xff0c;没道理不会大数据开发。 俗话说男追女隔座山&#xff0c;女追男隔层纱。 如果说零基础学大数据&#xff0c;感觉前面是一座山&#xff0c;那么只要你会java或者任意一门语言的stream流&#xff0c;那大数据就只隔了一层纱。 本文以…