mybatis - [08] mybatis-config.xml 详解

mybatis-config.xml中的标签需要按照一定顺序配置,否则会有以下提示。

 

 

001 || properties(属性)

(1)属性可以放在jdbc.properties中,也可以写在<property>标签中

<!-- 第一种写法 -->
<properties resource="jdbc.properties"/>

<!-- 第二种写法 -->
<properties resource="jdbc.properties">
    <property name="username" value="harley686"/>
    <property name="password" value="harley666"/>
</properties>

(2)jdbc.properties中进行如下配置

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

(3)无论在<properties>标签中引入.properties配置文件还是使用<property>标签设置的属性,都使用${value}的方式取值

<?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="jdbc.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>

    <!-- 配置mapper.xml -->
    <mappers>
        <mapper resource="com/harley/dao/UserMapper.xml"/>
    </mappers>
</configuration>

(4)测试结果

 

 

002 || settings(设置)

参考:https://mybatis.org/mybatis-3/zh_CN/configuration.html#settings

<settings>
  <setting name="cacheEnabled" value="true"/> <!-- 缓存是否开启 -->
  <setting name="lazyLoadingEnabled" value="true"/> <!--懒加载是否开启-->
  <setting name="aggressiveLazyLoading" value="true"/> <!--开启时,任何方法的调用都会加载该对象的所有延迟加载属性。否则,每个延迟加载属性会按需加载。-->
  <setting name="multipleResultSetsEnabled" value="true"/> <!--允许或禁止使用多结果集-->
  <setting name="useColumnLabel" value="true"/> <!--使用列标签代替列名-->
  <setting name="useGeneratedKeys" value="false"/> <!--自动生成主键是否开启,需要驱动支持-->
  <setting name="autoMappingBehavior" value="PARTIAL"/><!--MyBatis 自动映射行为-->
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/><!--指定发现自动映射目标未知列(或未知属性类型)的行为-->
  <setting name="defaultExecutorType" value="SIMPLE"/><!--配置默认的执行器。SIMPLE是普通的执行器;REUSE会复用预处理语句;BATCH可以实现批处理。-->
  <setting name="defaultStatementTimeout" value="25"/><!--设置超时时间,它决定驱动等待数据库响应的秒数。-->
  <setting name="defaultFetchSize" value="100"/><!--为驱动设置默认的fetchSize-->
  <setting name="safeRowBoundsEnabled" value="false"/><!--允许在嵌套语句中使用分页-->
  <setting name="safeResultHandlerEnabled" value="true"/><!--允许在嵌套语句中使用结果处理器-->
  <setting name="mapUnderscoreToCamelCase" value="false"/> <!--是否开启自动驼峰命名规则映射-->
  <setting name="localCacheScope" value="SESSION"/><!--利用本地缓存机制(Local Cache)防止循环引用和加速重复嵌套查询-->
  <setting name="jdbcTypeForNull" value="OTHER"/><!--指定当JDBC参数为null时使用的JDBC类型-->
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/><!--指定哪些方法触发延迟加载-->
  <setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/><!--指定默认的脚本语言-->
  <setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/><!--指定默认的枚举类型处理器-->
  <setting name="callSettersOnNulls" value="false"/><!--指定当结果集中值为null时,是否调用对象的 setter 方法-->
  <setting name="returnInstanceForEmptyRow" value="false"/><!--当查询结果为空时,是否返回对象实例-->
  <setting name="logPrefix" value="exampleLogPreFix_"/><!--指定 MyBatis 日志的前缀-->
  <setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/><!--指定 MyBatis 的日志实现-->
  <setting name="proxyFactory" value="CGLIB | JAVASSIST"/><!--指定 MyBatis 创建动态代理对象的工厂-->
  <setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/><!--指定自定义的VFS实现类,默认为null-->
  <setting name="useActualParamName" value="true"/><!--允许使用方法参数的真实名称-->
  <setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/><!--指定一个ConfigurationFactory类,用于创建Configuration对象-->
</settings>
 

 

003 || typeAliases(类型别名)

  mapper.xml中会有很多resultType="com.harley.pojo.User",结果集类型填写的是Pojo类的全限定名,全限定名比较长,为了使用方便,为Pojo类设置类型别名。

(1)在mybatis-config.xml中为Pojo类配置别名

<typeAliases>
    <typeAlias alias="User" type="com.harley.pojo.User"/>
</typeAliases>

(2)在mapper.xml中使用别名

<select id="getUserLike" resultType="User">
    select * from user where name like '%${value}%'
</select>

(3)测试结果

 

除了可以给类设置别名,还可以为包名设置别名

(1)为pojo类所在包设置别名

<typeAliases>
    <package name="com.harley.pojo"/>
</typeAliases>

(2)可以在mapper.xmlresultType="User"(User必须和类名一致),也可以使用@Alias("harleyUser")为pojo包下的实体类设置别名

注:使用lombok的注解@AllArgsConstructor@NoArgsConstructor@Data@ToString,可以省略getter/setter、有参/无参构造方法、toString方法的编写

(3)mapper.xmlresultType="User"需要和@Alias("User")对应,别名是小写,mapper.xml中使用时也必须是小写!

<select id="getUserLike" resultType="harleyUser">
    select * from user where name like '%${value}%'
</select>

(4)测试结果

总结:

(1)如果实体类数量比较少,使用第一种方式;如果实体类数量比较多,则使用第二种方式。

(2)第一种可以自定义别名,第二种不行。如果非要改,需要在实体类上加注解@Alias("别名")

 

004 || typeHandlers(类型处理器)

  用于实现Java类型和JDBC类型之间的相互转换。当Mybatis从数据库中读取数据或将数据写入数据库时,它会使用类型处理器来完成这些转换。

step1:自定义类型处理器

实现org.apache.ibatis.type.TypeHandler接口或者继承org.apache.ibatis.type.BaseTypeHandler抽象类

以下是将Java的LocalDate类型与JDBC的DATE类型进行转换的示例:

package com.harley.utils;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;
import java.time.LocalDate;

/**
 * @author harley
 * @since 2025-02-15 21:33:11
 */
// 标记Java类型
@MappedTypes(LocalDate.class)
// 标记JDBC类型
@MappedJdbcTypes(JdbcType.DATE)
public class LocalDateTypeHandler extends BaseTypeHandler<LocalDate> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType) throws SQLException {
        ps.setDate(i, Date.valueOf(parameter));
    }

    @Override
    public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Date date = rs.getDate(columnName);
        return date != null ? date.toLocalDate() : null;
    }

    @Override
    public LocalDate getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Date date = rs.getDate(columnIndex);
        return date != null ? date.toLocalDate() : null;
    }

    @Override
    public LocalDate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Date date = cs.getDate(columnIndex);
        return date != null ? date.toLocalDate() : null;
    }
}

step2:注册类型处理器

在mybatis-config.xml中,使用<typeHandlers>元素来注册自定义的类型处理器。可以通过指定类名的方式逐个注册,也可以指定包名让Mybatis自动扫描包下的所有类型处理器。

逐个注册

<typeHandlers>
    <typeHandler handler="com.harley.typeHandlers.LocalDateTypeHandler"/>
</typeHandlers>

批量注册

<typeHandlers>
    <package name="com.harley.typeHandlers"/>
</typeHandlers>

step3:使用类型处理器

注册完成后,mybatis会自动使用这些类型处理器进行Java类型和JDBC类型的转换。在SQL映射文件(xxxMapper.xml)中,无需额外配置即可使用。

<select id="selectUserByDate" resultType="com.harley.pojo.User">
    select * from mybatis.user where create_date = #{date}
</select>

这里的#{date}如果是LocalDate类型,Mybatis会自动使用LocalDateTypeHandler进行类型转换。

step4:显示指定类型处理器

在某些情况下,需要在SQL映射文件中显示指定使用的类型处理器。可以使用typeHandler属性来指定

<select id="selectUserByDate" resultType="com.harley.pojo.User">
    select * from user where create_date = #{date,typeHandler=com.harley.typeHandlers.LocalDateTypeHandler}
</select>

 

005 || objectFactory(对象工厂)

主要负责创建Java对象实例,使用场景如下:

(1)自定义对象创建逻辑

当默认的对象创建方式无法满足需求时,例如需要在创建对象时进行额外的初始化操作、注入特定的依赖或者根据不同条件创建不同类型的对象,就可以通过自定义ObjectFactory来实现。

(2)集成第三方依赖注入框架

如果项目中使用了如Spring这样的依赖注入框架,需要将依赖注入的逻辑与Mybatis的对象创建过程集成,自定义ObjectFactory可以实现这一点,确保创建的对象能正确注入所需的依赖。

(3)处理特殊对象创建需求

对于一些特殊的Java对象,可能需要特殊的创建方式,例如创建具有复杂构造函数的对象,或者需要从特定的对象池中获取对象,此时自定义ObjectFactory能满足这些特殊需求。

 

step1:自定义ObjectFactory

package com.harley.utils;

import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

import java.util.List;
import java.util.Properties;

/**
 * @author harley
 * @since 2025-02-15 21:50:00
 */
public class CustomObjectFactory extends DefaultObjectFactory {


    @Override
    public <T> T create(Class<T> type) {
        // 可以在这里添加自定义的对象创建逻辑
        System.out.println("Using custom object factory to create object of type:" + type.getName());
        return super.create(type);
    }

    @Override
    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        // 可以在这里添加自定义的对象创建逻辑
        System.out.println("Using custom object factory to create object of type: " + type.getName() + " with constructor args");
        return super.create(type, constructorArgTypes, constructorArgs);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以处理传入的属性配置
        super.setProperties(properties);
    }
}

step2:在mybatis-config.xml中配置自定义ObjectFactory

<objectFactory type="com.harley.utils.CustomObjectFactory">
    <!--可以在这里配置属性-->
    <property name="propertyName" value="propertyValue"/>
</objectFactory>

step3:使用自定义ObjectFactory

配置完成后,MyBatis在创建对象时会自动使用自定义的ObjectFactory。

当执行查询操作并将结果映射到Java对象时,Mybatis会调用自定义ObjectFactory的create方法来创建对象实例。

<select id="selectUser" resultType="com.harley.pojo.User">
    select * from mybatis.user where id = #{id}
</select>

当执行上述查询时,Mybatis会使用自定义的ObjectFactory来创建com.harley.pojo.User对象实例,并且会执行自定义ObjectFactory中重写的create方法里的逻辑。

比如,有一个pojo类为User,包含id、name、age属性。可以在自定义对象工厂(CustomObjectFactory)进行如下配置

    @Override
    public void setProperties(Properties properties) {
        // 从配置属性中获取默认名称和年龄
        this.defaultName = properties.getProperty("defaultName", "DefaultUser");
        this.defaultAge = Integer.parseInt(properties.getProperty("defaultAge", "20"));
        super.setProperties(properties);
    }

    @Override
    public <T> T create(Class<T> type) {
        if (type == User.class) {
            // 创建 User 对象并使用默认值初始化
            User user = new User();
            user.setName(defaultName);
            user.setAge(defaultAge);
            return (T) user;
        }
        return super.create(type);
    }

然后在mybatis-config.xml配置相关属性

<!-- 配置自定义 ObjectFactory -->
<objectFactory type="com.example.CustomObjectFactory">
    <property name="defaultName" value="John"/>
    <property name="defaultAge" value="25"/>
</objectFactory>

根据Resources.getResourceAsStream("mybatis-config.xml")作为inputStream,然后通过SqlSessionFactoryBuilder().build()方法返回sqlSessionFactory对象,该对象开启会话,进行查询时。会查到如下内容

User{id=1, name='John', age=25}

即为,可为pojo对象的属性进行初始化赋值,类似于Spring的依赖注入功能。

 

 

006 || plugins(插件)

常见的使用场景如下:

(1)分页功能:处理大量数据查询时,需要对结果进行分页展示。通过插件可以在SQL执行前动态修改SQL语句,添加分页逻辑,而无需在每个查询方法中手动编写分页代码。

(2)性能监控:对SQL语句的执行时间进行监控,帮助开发者找出性能瓶颈。插件可以在SQL执行前后记录时间,统计执行时长,并将这些信息输出到日志或监控系统中。

(3)数据加密与解密:在数据持久化到数据库之前对敏感数据进行加密,在从数据库查询数据时对加密数据进行解密。插件可以在参数处理和结果处理阶段插入加密和解密逻辑。

(4)SQL日志增强:除了MyBatis自带的日志功能,插件可以进一步增强SQL日志的输出,例如将SQL语句和实际参数进行格式化输出,方便调试和分析。

step1:自定义插件类

package com.harley.plugins;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;

import java.util.Properties;

/**
 * @author harley
 * @since 2025-02-15 22:15:06
 */
@Intercepts({
    @Signature(type = StatementHandler.class,method="prepare",args = {java.sql.Connection.class,Integer.class})
})
public class CustomPlugin implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 在目标方法执行前插入自定义逻辑
        System.out.println("Before statement prepare");
        Object result = invocation.proceed();
        System.out.println("After statement prepare");
        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以处理插件配置的属性
        Interceptor.super.setProperties(properties);
    }
}
  • @Intercepts@Signature注解用于指定要拦截的目标类和方法。这里拦截的是StatementHandler类的prepare方法。
  • intercept方法是插件的核心逻辑,在目标方法执行前后可以插入自定义代码
  • plugin方法用于将插件应用到目标对象上
  • setProperties方法用于处理插件配置的属性

step2:在mybatis-config.xml中配置插件

<plugins>
    <plugin interceptor="com.harley.plugins.CustomPlugin">
        <!--可以配置插件属性-->
        <property name="propertyName" value="propertyValue"/>
    </plugin>
</plugins>

 

 

007 || environments(环境配置)

可以配置多个环境,但是每个SqlSessionFactory实例只能选择一种环境。

mybatis默认的事务管理器(transactionManager)就是JDBC,连接池(dataSource)是POOLED

注意<environments>的default需要配置一个<environment>的id

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        </dataSource>
    </environment>
</environments>

 

011 || mappers(映射器)

 (1)使用<mapper>标签指定单个映射文件

<mappers>
    <mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>

(2)使用<mapper>标签指定单个映射接口

<mappers>
    <mapper class="com.example.mapper.UserMapper"/>
</mappers>

使用该方法,UserMapper映射接口和UserMapper.xml映射文件必须在同一个包下,且名称必须一致。

(3)使用<package>标签批量扫描包

<mappers>
    <package name="com.example.mapper"/>
</mappers>

使用该方法,UserMapper映射接口和UserMapper.xml映射文件必须在同一个包下,且名称必须一致。

 

 

 

— 业精于勤荒于嬉,行成于思毁于随 —

posted @   HOUHUILIN  阅读(265)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2023-06-05 curl - 详解
2023-06-05 SSM - 狂神的项目示例
点击右上角即可分享
微信分享提示