参考资料
- Mybatis配置类别名
- mybatis-spring-boot-autoconfigure
- 类型别名(typeAliases)
- SpringBoot五步配置Mybatis超简教程
目录
- 一. 使用场景
- 二. 前期准备
- 2.1 实体类
- 2.2 查询接口
- 三. 配置方式1 配置文件的方式
- 3.1 application.yml文件
- 3.2 SQL的XMl文件
- 3.3 效果
- 四. 配置方式2 配置类的方式
- 4.1 创建配置类,实现ConfigurationCustomizer
- 4.2 效果
- 五. 原理
- 六. 注意事项
一. 使用场景
- 如下面的代码所示,我们通过一个SQL查询数据,返回值类型为Ttag类型,我们需要通过
resultType
来指定Ttag
类的全路径com.example.jmw.entity.alias.Ttag
。一两个类还好说,如果使用的实体类数量过多,配置起来就很繁琐,我们需要为每一个类都指定全路径。 - 这个时候,就可以用到Mybatis的别名配置,我们可以指定实体类指定别名或者指定Mybatis扫描某个包,自动为该包下面的所有实体类都起别名。
<?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.example.jmw.mapper.alias_mapper.TtagMapper">
<select id="queryAllTtag" resultType="com.example.jmw.entity.alias.Ttag">
SELECT
*
FROM
t_tag
</select>
</mapper>
二. 前期准备
2.1 实体类
alias
包下的实体类
package com.example.jmw.entity.alias;
import lombok.Data;
import org.apache.ibatis.type.Alias;
@Data
@Alias("jmwUser")
public class EnumUser {
private String name;
private String sex;
}
package com.example.jmw.entity.alias;
import lombok.Data;
@Data
public class I18message {
private String code;
private String locale;
private String item;
}
package com.example.jmw.entity.alias;
import lombok.Data;
@Data
public class Ttag {
private String id;
private String name;
}
2.2 查询接口
import com.example.jmw.entity.alias.EnumUser;
import java.util.List;
public interface EnumUserMapper {
List<EnumUser> queryAllEnumUser();
}
import com.example.jmw.entity.alias.I18message;
import java.util.List;
public interface I18messageMapper {
List<I18message> queryAllI18message();
}
import com.example.jmw.entity.alias.Ttag;
import java.util.List;
public interface TtagMapper {
List<Ttag> queryAllTtag();
}
三. 配置方式1 配置文件的方式
3.1 application.yml文件
- 如果有多个包的话,中间用
,
分隔。
mybatis:
type-aliases-package: com.example.jmw.entity.alias;
3.2 SQL的XMl文件
- 我们之所以可以把
resultType
的值配置为jmwUser
,是因为我们在EnumUser
实体类上配置了@Alias("jmwUser")
注解,手动指定了EnumUser
实体类的别名。
<mapper namespace="com.example.jmw.mapper.alias_mapper.EnumUserMapper">
<select id="queryAllEnumUser" resultType="jmwUser">
SELECT
*
FROM
enumuser
</select>
</mapper>
- 如果我们没有通过
@Alias
注解手动指定别名,默认别名为类的名称,开头字母可以大写,不过推荐使用小写。
<mapper namespace="com.example.jmw.mapper.alias_mapper.I18messageMapper">
<select id="queryAllI18message" resultType="i18message">
SELECT
*
FROM
i18message
</select>
</mapper>
- 之前的使用全类名的方式,可以和别名的方式混用。
<mapper namespace="com.example.jmw.mapper.alias_mapper.TtagMapper">
<select id="queryAllTtag" resultType="com.example.jmw.entity.alias.Ttag">
SELECT
*
FROM
t_tag
</select>
</mapper>
3.3 效果
四. 配置方式2 配置类的方式
4.1 创建配置类,实现ConfigurationCustomizer
MyBatis-Spring-Boot-Starter
将自动寻找实现了ConfigurationCustomizer
接口的组件,然后会调用自定义 MyBatis 配置的方法来创建配置类。- 接口虽然无法直接实例化,但是可以配合函数式接口,通过lambda表达式的方式创建对象。
import org.apache.ibatis.type.TypeAliasRegistry;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class MybatisConfig {
/*
ConfigurationCustomizer是一个函数式接口,函数式接口只有一个方法customize(Configuration configuration)
通过ConfigurationCustomizer来创建Mybatis的配置
*/
@Bean
public ConfigurationCustomizer configurationCustomizer() {
// 下面这种写法是lambda式的简写的方式
return configuration -> {
// 打开别名注册类
TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
// 指定包下面所有的实体类都设置别名
typeAliasRegistry.registerAliases("com.example.jmw.entity.alias");
// 添加拦截器
// configuration.addInterceptor();
// 开启驼峰命名映射
// configuration.setMapUnderscoreToCamelCase(true);
};
}
}
或者可以通过实现接口这种方式
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeAliasRegistry;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
@org.springframework.context.annotation.Configuration
public class MybatisConfig implements ConfigurationCustomizer {
@Override
public void customize(Configuration configuration) {
// 打开别名注册类
TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
// 指定包下面所有的实体类都设置别名
typeAliasRegistry.registerAliases("com.example.jmw.entity.alias");
// 添加拦截器
// configuration.addInterceptor();
// 开启驼峰命名映射
// configuration.setMapUnderscoreToCamelCase(true);
}
}
4.2 效果
五. 原理
由下面的源码截图可知,Mybatis读取我们指定的包的路径,将包中所有的类都添加到别名的HashMap中。
六. 注意事项
之前在写这个demo时,遇到通过配置文件和配置类指定别名的时候,无法生效的问题。经过调查之后,发现自己在工程中还配置了Mybatis的拦截器,代码如下:
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.TypeAliasRegistry;
import org.mybatis.spring.SqlSessionFactoryBean;
//import org.mybatis.spring.boot.autoconfigure.SqlSessionFactoryBeanCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
// 注入数据源
@Resource
private DataSource dataSource;
// 注入自定义参数拦截器
@Resource
private MybatisParamInterceptor paramInterceptor;
@Bean
public SqlSessionFactory sqlSessionFactorySecondary() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
// 设置数据源
sqlSessionFactoryBean.setDataSource(dataSource);
// 设置拦截器(可设置多个)
Interceptor[] plugins = {paramInterceptor};
sqlSessionFactoryBean.setPlugins(plugins);
return sqlSessionFactoryBean.getObject();
}
}
😅😅😅
在此配置类中,我们使用了SqlSessionFactory
来添加Interceptor
,将SqlSessionFactory
添加到Spring的IOC容器中的这种方式,会导致Mybatis的配置文件或配置类失效。因为无论配置文件还是配置类,最终都是加载到SqlSessionFactory中,如果我们自己手动new一个SqlSessionFactory到Bean中的话,相当于重置了Mybatis为我们自动配置好的SqlSessionFactory。
💪💪💪
官方给我们提供了SqlSessionFactoryBeanCustomizer
接口来实现