学习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的增删改查是如何封装的、 好了缓存。太多重要的信息了。下一篇继续对这些比较重要的细节进行分析