MyBatis核心配置

MyBatis最核心主要就是全局配置文件和映射配置文件,全局配置文件主要用于设置MyBatis框架整体行为和属性,映射配置文件目的是配置应用对象与数据库数据关联映射。

01 全局配置文件

全局配置文件主要用于设置MyBatis框架整体行为和属性,比如属性配置、设置默认行为属性值、插件和环境等内容配置。需要注意,全局配置文件是有严格配置顺序要求,随意配置会导致解析报错。

MyBatis配置文件节点顺序参考文档:mybatis-3-config.dtd

xml 复制代码
<!-- 配置 -->
<configuration>
    <!-- 属性配置 -->
    <properties />
  
    <!-- 设置配置 -->
    <settings>
        <setting />
    </settings>
  
    <!-- 类型别名配置 -->
    <typeAliases>
        <typeAlias />
        <package />
    </typeAliases>
  
    <!-- 类型处理器 -->
    <typeHandlers>
        <package />
        <typeHandler />
    </typeHandlers>
  
    <!-- 对象工厂 -->
    <objectFactory />
  
    <!-- 插件配置 -->
    <plugins>
        <plugin />
    </plugins>
  
    <!-- 环境配置 -->
    <environments>
        <environment>
            <!-- 事务管理器 -->
            <transactionManager/>
            <!-- 连接池 -->
            <dataSource />
        </environment>
    </environments>

    <!-- 数据库厂商 -->
    <databaseIdProvider type=""></databaseIdProvider>

    <!-- 映射文件 -->
    <mappers>
        <mapper/>
    </mappers>
</configuration>

1.1 configuration

XML文档<configuration>节点为MyBatis全局配置文件根标签,解析对象就是核心配置类Configuration,内部标签解析后与Configuration内部属性一一对应。

1.2 properties

标签<properties>用来配置参数,比如最常见的数据库连接信息。为了避免配置参数与XML全局配置文件绑定,可以通过单独<properties>属性文件维护实现解耦,配置文件仅需通过${}引用即可。属性文件不仅支持相对和绝对路径文件,还支持网络路径属性文件。

xml 复制代码
<configuration>
  <!-- 相对路径 -->
  <properties resource="db.properties"/>
  <environments default="development">
      <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>
</configuration>
xml 复制代码
<configuration>
    <!-- 相对路径 -->
    <properties>
      <property name="jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
    </properties>
</configuration>

1.3 settings

MyBatis通过<settings>标签调整框架运行时行为,包括缓存、延迟加载和执行器类型等内容。

设置参数 描述 有效值 默认值
cacheEnabled 全局开启或关闭配置文件所有映射器已经配置缓存 true/false false
lazyLoadingEnabled 延迟加载全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系可通过设置fetchType属性覆盖开关状态 true/false false
aggressiveLazyLoading 主动惰性加载。当开启时,任何方法调用都会加载该对象所有延迟加载属性。 否则,都会按需加载延迟加载属性(参考 lazyLoadTriggerMethods)。需要注意的是,在3.4.1及之前版本,默认值为true true / false false
multipleResultSetsEnabled 是否允许单一语句返回多结果集(需要兼容驱动),已废弃 true/false false
useColumnLabel 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动相关文档,或通过对比测试来观察 true/false false
useGeneratedKeys 允许JDBC支持自动生成主键,需要数据库驱动支持。 设置为true,强制使用自动生成主键,尽管驱动不兼容但仍可正常工作(比如 Derby) true/false false
autoMappingBehavior 指定自动映射数据库列到字段或属性。 NONE取消自动射,PARTIAL自动映射没有定义嵌套结果集结果集, FULL自动映射任意复杂的结果集 NONEPARTIALFULL PARTIAL
autoMappingUnknownColumnBehavior 指定自动映射目标未知列或者未知属性类型行为。 NONE不做任何反应,WARNING输出提醒日志(org.apache.ibatis.session.AutoMappingUnknownColumnBehavior日志等级必须设置为WARN),FAILING:映射失败 (抛出 SqlSessionException)异常 NONEWARNINGFAILING NONE
defaultExecutorType 配置默认执行器。SIMPLE普通执行器,REUSE执行器会重用预处理语句(PreparedStatement),BATCH执行器重用语句并执行批量更新 SIMPLEREUSEBATCH SIMPLE
defaultStatementTimeout 设置超时时间,决定驱动等待数据库响应秒数 正整数 未设置
defaultFetchSize 设置驱动结果集获取数量(fetchSize)建议值。此参数只可在查询设置被覆盖 正整数 未设置
safeRowBoundsEnabled 是否允许嵌套语句使用分页(RowBounds)。如果允许设置为false true/false false
safeResultHandlerEnabled 是否允许嵌套语句使用结果处理器(ResultHandler)。如果允许设置为false true/false false
mapUnderscoreToCamelCase 是否开启自动驼峰命名规则映射 true/false False
localCacheScope 利用本地缓存机制(Local Cache)防止循环引用和加速重复嵌套查询。 SESSION为缓存会话执行所有查询,STATEMENT为本地缓存仅用于执行语句,相同SqlSession不同查询不会进行缓存 SESSIONSTATEMENT SESSION
jdbcTypeForNull 当没有提供特定JDBC类型时,指定空值JDBC类型 NULLVARCHAROTHER OTHER
lazyLoadTriggerMethods 指定哪个对象方法触发一次延迟加载。用逗equals,clone,hashCode,toString 参考描述 参考描述
defaultScriptingLanguage 指定动态SQL生成默认语言。一个类型别名或完全限定类名,默认值为org.apache.ibatis.scripting.xmltags.XMLLanguageDriver 参考描述 参考描述
defaultEnumTypeHandler 指定Enum默认类型处理器TypeHandler 。可以为一个类型别名或完全限定类名,默认值org.apache.ibatis.type.EnumTypeHandler(新增于3.4.5) 参考描述 参考描述
callSettersOnNulls 指定结果集值为null是否调用映射对象setter(map对象为 put)方法,如果有依赖Map.keySet()null值进行初始化比较有用。需要注意的是,基本类型(int、boolean等)不能设置成null。 true / false false
returnInstanceForEmptyRow 当返回行的所有列都是空时,MyBatis默认返回null。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集 (i.e. collectioin and association)。(从3.4.2开始)返回行所有列为空时,是否默认返回null。 如果开启设置,MyBatis会返回一个空实例。 注意的是,同样也适用于嵌套结果集(新增于3.4.2) true/false false
logPrefix 指定MyBatis增加到日志名称前缀 字符串 未设置
logImpl 指定所用日志具体实现,未指定时将自动查找。可选值包括SLF4J、LOG4J(3.5.9 起废弃)、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING和NO_LOGGING 参考描述 未设置
proxyFactory 指定创建具有延迟加载对象所用到的代理工具。可选值包括CGLIB (3.5.10 起废弃)和JAVASSIST/CGLIBJAVASSIST JAVASSIST
vfsImpl 指定VFS实现。可选值为自定义VFS实现类全限定名,以逗号分隔 参考描述 未设置
useActualParamName 是否允许使用方法参数名作为语句参数名称。前置条件是采用Java 8加上-parameters选项编译(新增于3.4.1) true / false true
configurationFactory 指定提供Configuration实例工厂的类,必须包含static Configuration getConfiguration()方法,用于加载反序列化对象延迟加载属性值(新增于 3.2.3) 类型别名或全类名 未设置
nullableOnForEach 为 foreach标签nullable属性指定默认值(新增于 3.5.9) true/false false
argNameBasedConstructorAutoMapping 构造器是否基于参数名称自动映射,而不是依赖列顺序(新增于 3.5.10) true/false false

1.4 typeAliases

TypeAlias也就是类型别名,与Linux系统alias一样,主要用来简化类名全路径拼写。需要注意,如果涉及多库场景,可能存在类型重名问题。

xml 复制代码
<configuration>
    <!-- 类型别名 -->
    <typeAliases>
        <typeAlias alias="user" type="com.feiyu.model.User" />
    </typeAliases>
</configuration>
xml 复制代码
<?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.boge.mapper.UserMapper">
    <!-- 开启二级缓存 -->
    <cache/>
    
    <resultMap id="BaseResultMap" type="user">
        <id property="id" column="id" jdbcType="INTEGER"/>
        <result property="userName" column="user_name" jdbcType="VARCHAR"/>
        <result property="realName" column="real_name" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
        <result property="dId" column="d_id" jdbcType="INTEGER"/>
    </resultMap>
    
    <select id="selectUserByBean" parameterType="user" resultType="user">
        select 
          *
        from 
          t_user
        where user_name = #{userName}
    </select>
</mapper>

MyBatis通过TypeAliasRegistry类,预先维护很多系统类型别名。

java 复制代码
public class TypeAliasRegistry {
    private final Map<String, Class<?>> typeAliases = new HashMap<>();

    public TypeAliasRegistry() {
        registerAlias("string", String.class);

        registerAlias("byte", Byte.class);
        registerAlias("long", Long.class);
        registerAlias("short", Short.class);
        registerAlias("int", Integer.class);
        registerAlias("integer", Integer.class);
        registerAlias("double", Double.class);
        registerAlias("float", Float.class);
        registerAlias("boolean", Boolean.class);

        registerAlias("byte[]", Byte[].class);
        registerAlias("long[]", Long[].class);
        registerAlias("short[]", Short[].class);
        registerAlias("int[]", Integer[].class);
        registerAlias("integer[]", Integer[].class);
        registerAlias("double[]", Double[].class);
        registerAlias("float[]", Float[].class);
        registerAlias("boolean[]", Boolean[].class);

        registerAlias("_byte", byte.class);
        registerAlias("_long", long.class);
        registerAlias("_short", short.class);
        registerAlias("_int", int.class);
        registerAlias("_integer", int.class);
        registerAlias("_double", double.class);
        registerAlias("_float", float.class);
        registerAlias("_boolean", boolean.class);

        registerAlias("_byte[]", byte[].class);
        registerAlias("_long[]", long[].class);
        registerAlias("_short[]", short[].class);
        registerAlias("_int[]", int[].class);
        registerAlias("_integer[]", int[].class);
        registerAlias("_double[]", double[].class);
        registerAlias("_float[]", float[].class);
        registerAlias("_boolean[]", boolean[].class);

        registerAlias("date", Date.class);
        registerAlias("decimal", BigDecimal.class);
        registerAlias("bigdecimal", BigDecimal.class);
        registerAlias("biginteger", BigInteger.class);
        registerAlias("object", Object.class);

        registerAlias("date[]", Date[].class);
        registerAlias("decimal[]", BigDecimal[].class);
        registerAlias("bigdecimal[]", BigDecimal[].class);
        registerAlias("biginteger[]", BigInteger[].class);
        registerAlias("object[]", Object[].class);

        registerAlias("map", Map.class);
        registerAlias("hashmap", HashMap.class);
        registerAlias("list", List.class);
        registerAlias("arraylist", ArrayList.class);
        registerAlias("collection", Collection.class);
        registerAlias("iterator", Iterator.class);

        registerAlias("ResultSet", ResultSet.class);
    }
}

1.5 typeHandler

TypeHandler也就是类型处理器,用于实现Java类型对象与数据库JDBC类型互相转化实现。默认情况下,Mybatis通过TypeHandlerRegistry已注册很多TypeHandler,这也就是为啥查询会自动处理各种数据类型。

java 复制代码
public final class TypeHandlerRegistry {
    private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
    private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();

    public TypeHandlerRegistry() {
        this(new Configuration());
    }
    
    public TypeHandlerRegistry(Configuration configuration) {
        this.unknownTypeHandler = new UnknownTypeHandler(configuration);

        register(Boolean.class, new BooleanTypeHandler());
        register(boolean.class, new BooleanTypeHandler());
        register(JdbcType.BOOLEAN, new BooleanTypeHandler());
        register(JdbcType.BIT, new BooleanTypeHandler());

        register(Byte.class, new ByteTypeHandler());
        register(byte.class, new ByteTypeHandler());
        register(JdbcType.TINYINT, new ByteTypeHandler());

        register(Short.class, new ShortTypeHandler());
        register(short.class, new ShortTypeHandler());
        register(JdbcType.SMALLINT, new ShortTypeHandler());

        register(Integer.class, new IntegerTypeHandler());
        register(int.class, new IntegerTypeHandler());
        register(JdbcType.INTEGER, new IntegerTypeHandler());

        register(Long.class, new LongTypeHandler());
        register(long.class, new LongTypeHandler());

        register(Float.class, new FloatTypeHandler());
        register(float.class, new FloatTypeHandler());
        register(JdbcType.FLOAT, new FloatTypeHandler());

        register(Double.class, new DoubleTypeHandler());
        register(double.class, new DoubleTypeHandler());
        register(JdbcType.DOUBLE, new DoubleTypeHandler());

        register(Reader.class, new ClobReaderTypeHandler());
        register(String.class, new StringTypeHandler());
        register(String.class, JdbcType.CHAR, new StringTypeHandler());
        register(String.class, JdbcType.CLOB, new ClobTypeHandler());
        register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
        register(String.class, JdbcType.LONGVARCHAR, new StringTypeHandler());
        register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
        register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
        register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
        register(JdbcType.CHAR, new StringTypeHandler());
        register(JdbcType.VARCHAR, new StringTypeHandler());
        register(JdbcType.CLOB, new ClobTypeHandler());
        register(JdbcType.LONGVARCHAR, new StringTypeHandler());
        register(JdbcType.NVARCHAR, new NStringTypeHandler());
        register(JdbcType.NCHAR, new NStringTypeHandler());
        register(JdbcType.NCLOB, new NClobTypeHandler());

        register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
        register(JdbcType.ARRAY, new ArrayTypeHandler());

        register(BigInteger.class, new BigIntegerTypeHandler());
        register(JdbcType.BIGINT, new LongTypeHandler());

        register(BigDecimal.class, new BigDecimalTypeHandler());
        register(JdbcType.REAL, new BigDecimalTypeHandler());
        register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
        register(JdbcType.NUMERIC, new BigDecimalTypeHandler());

        register(InputStream.class, new BlobInputStreamTypeHandler());
        register(Byte[].class, new ByteObjectArrayTypeHandler());
        register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
        register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
        register(byte[].class, new ByteArrayTypeHandler());
        register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
        register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
        register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
        register(JdbcType.BLOB, new BlobTypeHandler());

        register(Object.class, unknownTypeHandler);
        register(Object.class, JdbcType.OTHER, unknownTypeHandler);
        register(JdbcType.OTHER, unknownTypeHandler);

        register(Date.class, new DateTypeHandler());
        register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
        register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
        register(JdbcType.TIMESTAMP, new DateTypeHandler());
        register(JdbcType.DATE, new DateOnlyTypeHandler());
        register(JdbcType.TIME, new TimeOnlyTypeHandler());

        register(java.sql.Date.class, new SqlDateTypeHandler());
        register(java.sql.Time.class, new SqlTimeTypeHandler());
        register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());

        register(String.class, JdbcType.SQLXML, new SqlxmlTypeHandler());

        register(Instant.class, new InstantTypeHandler());
        register(LocalDateTime.class, new LocalDateTimeTypeHandler());
        register(LocalDate.class, new LocalDateTypeHandler());
        register(LocalTime.class, new LocalTimeTypeHandler());
        register(OffsetDateTime.class, new OffsetDateTimeTypeHandler());
        register(OffsetTime.class, new OffsetTimeTypeHandler());
        register(ZonedDateTime.class, new ZonedDateTimeTypeHandler());
        register(Month.class, new MonthTypeHandler());
        register(Year.class, new YearTypeHandler());
        register(YearMonth.class, new YearMonthTypeHandler());
        register(JapaneseDate.class, new JapaneseDateTypeHandler());

        // issue #273
        register(Character.class, new CharacterTypeHandler());
        register(char.class, new CharacterTypeHandler());
    }
}
java 复制代码
public class MyTypeHandler extends BaseTypeHandler<String> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String name = rs.getString(columnName);
        if("sys".equals(name)){
            return String.format("<%s>", name);
        }
        return name;
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String name = rs.getString(columnIndex);
        if("sys".equals(name)){
            return String.format("<%s>", name);
        }
        return name;
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String name = cs.getString(columnIndex);
        if("sys".equals(name)){
            return String.format("<%s>", name);
        }
        return name;
    }
}
xml 复制代码
<configuration>
  <typeHandlers>
      <typeHandler handler="com.feiyu.type.MyTypeHandler"/>
  </typeHandlers>
</configuration>

1.6 objectFactory

获取到数据库结果集后就需要转换为实体对象实例,转换过程并不明确实体类型,也就不能直接使用new方式创建,只能借助反射方式创建。所以,MyBatis提供ObjectFactory工厂类接口,用于实现实体类对象创建。

java 复制代码
public interface ObjectFactory {
    // 设置参数时调用
    default void setProperties(Properties properties) {
        // NOP
    }
    // 创建对象(调用无参构造函数)
    <T> T create(Class<T> type);
    // 创建对象(调用带参数构造函数)
    <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
    // 判断是否集合类
    <T> boolean isCollection(Class<T> type);
}

ObjectFactory默认提供实现类DefaultObjectFactory,底层也就是通过反射模式创建所需实体对象,不过用户可以自定义对象工厂。

xml 复制代码
public class MyObjectFactory extends DefaultObjectFactory {
    @Override
    public Object create(Class type) {
        System.out.println("创建对象方法: " + type);
        if (type.equals(User.class)) {
            User blog = (User) super.create(type);
            blog.setUserName("feiyu factory");
            blog.setId(1);
            blog.setRealName("feiyu");
            return blog;
        }
        Object result = super.create(type);
        return result;
    }
}
xml 复制代码
<configuration>
    <objectFactory type="com.feiyu.objectfactory.MyObjectFactory"/>
</configuration>

1.7 plugins

跟很多框架类似,MyBatis预留插件接口扩展实现执行器(Executor)、参数处理器(ParameterHandler)、结果处理器(ResultSetHandler)和Statement处理器(StatementHandler)。

官方参考文档地址:mybatis.org/mybatis-3/z...

1.8 environments

<environments>标签用来管理数据库环境,比如配置开发、测试和生产环境数据库。<environment>标签代表一个数据环境,可以配置对应事务管理器(<transactionManager>)和数据源(<dataSource>)。

<transactionManager>标签:如果配置为JDBC,则会使用Connection对象commit、rollback和close管理事务。如果配置成MANAGED,会把事务交给容器来管理,比如JBOSS,Weblogic。

xml 复制代码
<configuration>
  <environments default="development">
        <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>
</configuration>

1.9 databaseIdProvider

MyBatis可以根据不同数据库厂商执行不同语句,基于映射语句中databaseId属性支持。首先精确匹配databaseId属性语句,其次匹配不带databaseId属性配置语句。

xml 复制代码
<configuration>
  <databaseIdProvider type="DB_VENDOR">
    <property name="MySQL" value="mysql"/>       
    <property name="Oracle" value="oracle" />
  </databaseIdProvider>
</configuration>

需要注意,数据库厂商是解析mybatis配置时根据数据库厂商驱动获取到,比如MySQL固定值就是MySQL

java 复制代码
public class XMLConfigBuilder extends BaseBuilder {
    private void databaseIdProviderElement(XNode context) throws Exception {
        DatabaseIdProvider databaseIdProvider = null;
        if (context != null) {
            String type = context.getStringAttribute("type");
            // awful patch to keep backward compatibility
            if ("VENDOR".equals(type)) {
                type = "DB_VENDOR";
            }
            Properties properties = context.getChildrenAsProperties();
            databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();
            databaseIdProvider.setProperties(properties);
        }
        Environment environment = configuration.getEnvironment();
        if (environment != null && databaseIdProvider != null) {
            String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
            configuration.setDatabaseId(databaseId);
        }
    }
}

1.10 mappers

<mappers>标签配置映射器,也就是Mapper.xml路径,配置目的是让MyBatis启动扫描这些映射器创建映射关系。MyBatis提供四种方式配置,包括相对路径、绝对路径、Mapper类完全限定名和包路径。

MyBatis官方Mapper参考文档地址:mybatis.org/mybatis-3/z...

xml 复制代码
<configuration>
  <mappers>
    <!-- 相对路径 -->
    <mapper resource="UserMapper.xml"/>
  </mappers>
</configuration>
xml 复制代码
<configuration>
  <mappers>
    <!-- 相对路径 -->
    <mapper resource="file:///app/mybatis/mappers/UserMapper.xml"/>
  </mappers>
</configuration>
xml 复制代码
<configuration>
  <mappers>
    <!-- 映射器接口包名 -->
    <package class="com.feiyu.mapper"/>
  </mappers>
</configuration>
xml 复制代码
<configuration>
  <mappers>
    <!-- 映射器接口完全限定类名 -->
    <mapper name="com.feiyu.mapper.UserMapper"/>
  </mappers>
</configuration>

02 映射配置文件

MyBatis持久化框架提供查询、插入、更新和删除操作与Java方法映射,映射关系通过MyBatis映射文件维护,通常称为Mapper XML文件实现。

MyBatis官方映射文件路径:mybatis.org/mybatis-3/z...

功能 内容
定义SQL查询和操作 Mapper XML文件定义查询、插入、更新和删除操作,可以包含参数和结果映射
参数映射 Mapper XML文件指定如何映射方法参数到SQL语句参数
结果映射 定义如何将SQL查询结果映射到Java对象
命名空间 Mapper XML文件通过唯一命名空间标识Mapper作用域,Mapper接口通常与Mapper XML文件命名空间相对应
动态 SQL Mapper XML文件支持动态SQL,能够根据条件生成不同SQL查询
xml 复制代码
<mapper>
    <!-- 命名空间缓存配置 -->
    <cache/>
    <!-- 引用其它命名空间缓存配置 -->
    <cache-ref/>

    <!-- 描述数据库结果集与加载对象映射 -->
    <resultMap/>

    <!-- 老式风格参数映射, 已被废弃 -->
    <parameterMap/>

    <!-- 可重用语句块, 可被其它语句引用 -->
    <sql/>

    <!-- 插入语句映射 -->
    <insert/>

    <!-- 更新语句映射 -->
    <update/>

    <!-- 删除语句映射 -->
    <delete/>

    <!-- 查询语句映射 -->
    <query/>
</mapper>

2.1 cache

MyBatis内置一个强大事务性查询缓存机制,可以非常方便配置和定制。默认情况下,仅开启本地会话缓存,如果需要开启全局二级缓存,需要再映射配置文件添加<cache/>标签开启。

xml 复制代码
<cache />
选项 明细
缓存效果 1、映射语句文件所有select语句结果都会被缓存 2、 映射语句文件所有insert、update和delete语句会刷新缓存 3、缓存会使用最近最少算法(LRU, Least Recently Used)清除不需要缓存 4、 缓存不会定时进行刷新(也就是说,没有刷新间隔) 5、缓存会保存列表或对象1024个引用 6、缓存会被视为读/写缓存,也就是缓存对象并不共享,修改属于线程安全
缓存算法 1、 LRU(最近最少使用):移除最长时间不被使用对象 2、FIFO(先进先出):按照对象进入缓存顺序移除 3、SOFT(软引用):基于垃圾回收器状态和软引用规则移除对象 4、WEAK(弱引用):更积极地基于垃圾收集器状态和弱引用规则移除对象
MyBatis也支持自定义缓存,或者使用第三方缓存方案创建适配器,配置自定义缓存处理器。
xml 复制代码
<mapper>
  <cache type="com.feiyu.model.MyCustomCache">
    <property name="cacheFile" value="/tmp/my-custom-cache.tmp"/>
  </cache>
</mapper>

2.2 cache-ref

默认情况下,某一命名空间语句,只会使用当前命名空间缓存进行缓存或刷新。如果需要使用其他命名空间缓存共享数据,就需要使用<cache-ref>进行引用才能使用。

xml 复制代码
<mapper>
  <cache-ref namespace="com.feiyu.mapper.SomeMapper"/>
</mapper>

2.3 resultMap

<resultMap>标签定义SQL查询结果字段与实体属性映射关系,实现查询SQL按照映射关系加载Java实体对象。

xml 复制代码
<mapper>
    <resultMap id="BaseResultMap" type="user">
        <id property="id"           column="id"        jdbcType="INTEGER"/>
        <result property="userName" column="user_name" jdbcType="VARCHAR"/>
        <result property="realName" column="real_name" jdbcType="VARCHAR"/>
        <result property="password" column="password"  jdbcType="VARCHAR"/>
        <result property="age"      column="age"       jdbcType="INTEGER"/>
    </resultMap>
</mapper>

2.4 sql

<sql>标签用来定义可重用SQL代码片段,以便在其它语句可以使用。 参数可以静态确定,通过不同<include>标签定义不同参数值。

xml 复制代码
<mapper>
    <sql id="dynamicSql">${table}.id, ${table}.username, ${table}.password</sql>
    <select id="selectUsers" resultType="map">
        select
            <include refid="dynamicSql"><property name="table" value="t1"/></include>
        from t_user t1
    </select>
</mapper>

2.5 select

xml 复制代码
<select
  	id="selectPerson"
  	parameterType="int"
  	parameterMap="deprecated"
  	resultType="hashmap"
  	resultMap="personResultMap"
  	flushCache="false"
  	useCache="true"
  	timeout="10"
  	fetchSize="256"
  	statementType="PREPARED"
  	resultSetType="FORWARD_ONLY"/>
属性 描述
id 命名空间唯一标识符,对应接口方法
parameterType 输入参数类型。默认为未设置,MyBatis能根据类型处理器(TypeHandler)推断参数类型
parameterMap 输入参数映射,已被废弃
resultType 输出结果类型
resultMap 输出结果映射,不能同时与resultType一起使用
flushCache 是否清空本地和二级缓存,默认为false
useCache 是否使用二级缓存,默认为true
timeout 执行SQL语句超时毫秒数,默认未设置(数据库配置决定)
fetchSize 每次拉取数据库结果集行数,默认未设置(数据库配置决定)
statementType 语句类型,可选项为STATEMENT、PREPARED或CALLABLE
resultSetType 数据库游标处理方式,可选项为FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE或DEFAULT(等价于未设置),默认未设置(数据库配置决定)
databaseId 数据库厂商标识,与<databaseIdProvider>配置选择数据库类型
resultOrdered 是否指定构造方法参数顺序,属于<resultMap>/<constructor>标签属性,默认false
resultSets 指定存储过程多个结果集,多结果集使用英文逗号分隔

2.5.1 resultOrdered

resultOrdered用于指定实体类构造方法参数顺序,位于<resultMap>/<constructor> 标签属性。

java 复制代码
@Data
public class User {
    private int id;
    private String username;
    private String password;

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
}

xml

ini 复制代码
<resultMap id="userResultMap" type="com.feiyu.model.User">
    <constructor resultOrdered="true">
        <idArg column="id" javaProperty="id"/>
        <arg column="username" javaProperty="username"/>
        <arg column="password" javaProperty="password"/>
    </constructor>
</resultMap>

2.5.2 resultSets

resultSets 用于存储过程指定多个结果集处理方式。普通查询通常只返回一个结果集,但存储过程可以返回多个结果集。

xml 复制代码
<!-- 存储过程返回用户和订单两个结果集 -->
<select id="getUserAndOrders" statementType="CALLABLE" resultSets="UserResultMap,OrderResultMap">
    {CALL getUserAndOrders(#{userId, jdbcType=INTEGER, mode=IN, javaType=int})}
</select>

<resultMap id="UserResultMap" type="com.feiyu.model.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="password" column="password"/>
</resultMap>
<resultMap id="OrderResultMap" type="com.feiyu.model.Order">
    <id property="id" column="id"/>
    <result property="orderId" column="order_id"/>
    <result property="amount" column="amount"/>
</resultMap>

2.5.3 resultSetType

resultSetType 指定如何处理数据库游标(结果集类型),影响结果集滚动和更新行为。常见值有FORWARD_ONLYSCROLL_INSENSITIVESCROLL_SENSITIVE

  1. FORWARD_ONLY:结果集只能向前滚动(默认)
  2. SCROLL_INSENSITIVE:结果集可以滚动,对结果集更改不敏感
  3. SCROLL_SENSITIVE:结果集可以滚动,对结果集更改敏感
xml 复制代码
<select id="get" resultSetType="SCROLL_INSENSITIVE" resultType="com.feiyu.model.User">
    SELECT id, username, password FROM users WHERE id = #{id}
</select>

2.5.4 databaseId

xml 复制代码
<mapper>
  <select id="SelectTime"   resultType="String" databaseId="mysql">
      select now() from dual
  </select>
  <select id="SelectTime"   resultType="String" databaseId="oracle">
      select 'oralce' || to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
  </select>
</mapper>

2.6 insert

xml 复制代码
<mapper>
    <insert
        id="insertAuthor"
        parameterType="com.feiyu.model.Author"
        flushCache="true"
        statementType="PREPARED"
        keyProperty=""
        keyColumn=""
        useGeneratedKeys=""
        timeout="20"/>
</mapper>
属性 描述
id 命名空间唯一标识符,对应接口方法
parameterType 输入参数类型。默认为未设置,MyBatis能根据类型处理器(TypeHandler)推断参数类型
parameterMap 输入参数映射,已被废弃
flushCache 是否清空本地和二级缓存,默认为true
timeout 执行SQL语句超时毫秒数,默认未设置(数据库配置决定)
statementType 语句类型,可选项为STATEMENT、PREPARED或CALLABLE
useGeneratedKeys 是否使用自动生成的主键,默认值false
keyProperty 主键属性名。如果不止生成一个列,可以用逗号分隔多个属性名称。默认未设置
keyColumn 主键对应的数据库列名。如果不止生成一个列,可以用逗号分隔多个属性名称。
databaseId 数据库厂商标识,与<databaseIdProvider>配置选择数据库类型

2.7 update

xml 复制代码
<mapper>
    <update
        id="updateAuthor"
        parameterType="com.feiyu.model.Author"
        flushCache="true"
        statementType="PREPARED"
        timeout="20">
</mapper>
属性 描述
id 命名空间唯一标识符,对应接口方法
parameterType 输入参数类型。默认为未设置,MyBatis能根据类型处理器(TypeHandler)推断参数类型
parameterMap 输入参数映射,已被废弃
flushCache 是否清空本地和二级缓存,默认为true
timeout 执行SQL语句超时毫秒数,默认未设置(数据库配置决定)
statementType 语句类型,可选项为STATEMENT、PREPARED或CALLABLE
useGeneratedKeys 是否使用自动生成的主键,默认值false
keyProperty 主键属性名。如果不止生成一个列,可以用逗号分隔多个属性名称。默认未设置
keyColumn 主键对应的数据库列名。如果不止生成一个列,可以用逗号分隔多个属性名称。
databaseId 数据库厂商标识,与<databaseIdProvider>配置选择数据库类型

2.8 delete

xml 复制代码
<mapper>
    <delete
        id="deleteAuthor"
        parameterType="com.feiyu.model.Author"
        flushCache="true"
        statementType="PREPARED"
        timeout="20">
</mapper>
属性 描述
id 命名空间唯一标识符,对应接口方法
parameterType 输入参数类型。默认为未设置,MyBatis能根据类型处理器(TypeHandler)推断参数类型
parameterMap 输入参数映射,已被废弃
flushCache 是否清空本地和二级缓存,默认为true
timeout 执行SQL语句超时毫秒数,默认未设置(数据库配置决定)
statementType 语句类型,可选项为STATEMENT、PREPARED或CALLABLE
useGeneratedKeys 是否使用自动生成的主键,默认值false
databaseId 数据库厂商标识,与<databaseIdProvider>配置选择数据库类型
相关推荐
豌豆花下猫33 分钟前
Python 潮流周刊#112:欢迎 AI 时代的编程新人
后端·python·ai
Electrolux1 小时前
你敢信,不会点算法没准你赛尔号都玩不明白
前端·后端·算法
whhhhhhhhhw1 小时前
Go语言-fmt包中Print、Println与Printf的区别
开发语言·后端·golang
ん贤2 小时前
Zap日志库指南
后端·go
Spliceㅤ2 小时前
Spring框架
java·服务器·后端·spring·servlet·java-ee·tomcat
IguoChan2 小时前
10. Redis Operator (3) —— 监控配置
后端
Micro麦可乐4 小时前
前端与 Spring Boot 后端无感 Token 刷新 - 从原理到全栈实践
前端·spring boot·后端·jwt·refresh token·无感token刷新
方块海绵4 小时前
浅析 MongoDB
后端
中东大鹅4 小时前
SpringBoot配置外部Servlet
spring boot·后端·servlet
一语长情4 小时前
从《架构整洁之道》看编程范式:结构化、面向对象与函数式编程精要
后端·架构·代码规范