自定义mybatis插件,就是拦截mybatis框架指定的方法,然后对方法进行增强的过程,类似Spring的AOP。今天参考<mybatis从入门到精通>中的案例,定义一个对mybatis的map类型出参中的key从下划线转驼峰的插件,看看mybatis的插件是如何定义出来的
老规矩,先看目录
1、测试环境目录结构
projectName/
|src/
|—— test/
| |——java/
| |——example/
| |——plugin/
| |—— CameHumpInterceptor.java
| |—— MapperTest.java
| |——resources/
| |——mapper/
| |——MapperTest.xml
| |——mybatis/
| |——mybatis-config.xml
解释一下各个类及文件的作用
CameHumpInterceptor.java:自定义的mybatis下划线转驼峰插件
MapperTest.java:测试类
MapperTest.xml:mybatis的mapper xml文件
mybatis-config.xml:mybatis的配置文件
2、编写测试的mapper文件
MapperTest.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="example.MapperTest">
<select id="selectTableNameMapById" resultType="java.util.Map">
SELECT table_name,operate_type FROM testTable WHERE id = 1
</select>
</mapper>
可以看到,这个statement的结果是一个Map类型。我们的任务就是将table_name以及operate_type这两个下划线的key改成驼峰,即:tableName和operateType。
3、定义mybatis插件,拦截mybatis出参
package example.plugin;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;
import java.sql.Statement;
import java.util.*;
/**
* 类 描 述:字段名,下划线转驼峰插件
*/
//拦截的类和方法,除了ResultSetHandler.class,还有另外3个也可以拦截的类,可以自己查查用法
@Intercepts(
@Signature(
type = ResultSetHandler.class,
method = "handleResultSets",
args = {Statement.class})
)
@SuppressWarnings({"unchecked", "rawtypes"})
public class CameHumpInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable{
List<Object> list = (List<Object>) invocation.proceed();
for (Object object : list) {
//如果是map类型,就对map的key进行转换
if (object instanceof Map) {
processMap(((Map) object));
} else {
break;
}
}
return list;
}
/**
* 处理map类型
* @param map
*/
private void processMap(Map<String,Object> map) {
Set<String> keySet = new HashSet<String>(map.keySet());
for (String key : keySet) {
//将以大写开头的字符串转换为小写,如果包含下划线也会处理为驼峰
//此处只通过这两个简单的标识来判断是否进行转换
if ((key.charAt(0) >= 'A' && key.charAt(0) <= 'Z') || key.indexOf("_") >= 0) {
Object value = map.get(key);
map.remove(key);
map.put(underlineToCamelhump(key), value);
}
}
}
private String underlineToCamelhump(String inputString) {
StringBuilder sb = new StringBuilder();
boolean nextUpperCase = false;
for (int i = 0; i < inputString.length(); i++) {
char c = inputString.charAt(i);
if (c == '_') {
if (sb.length() > 0) {
nextUpperCase = true;
}
}else {
if (nextUpperCase) {
sb.append(Character.toUpperCase(c));
nextUpperCase = false;
}else {
sb.append(Character.toLowerCase(c));
}
}
}
return sb.toString();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
4、配置mybatis插件
从mybatis-config.xml中增加拦截器
<?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>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--配置mybatis插件。对mybatis的Map出参,key从下换线转成驼峰-->
<plugins>
<plugin interceptor="example.plugin.CameHumpInterceptor"></plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value=""/>
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="111111"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/MapperTest.xml"/>
</mappers>
</configuration>
5、测试类
public class MapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init(){
try {
Reader reader = Resources.getResourceAsReader("mybatis/mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testSelectAll(){
SqlSession sqlSession = sqlSessionFactory.openSession();
//example.MapperTest是mapper文件的namespace,selectTableNameMapById是statement的id
Map<String,String> map = sqlSession.selectOne("example.MapperTest.selectTableNameMapById");
System.out.println(JSONObject.toJSONString(map));
}
}
结果:
19:23:55.454 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6a84a97d]
19:23:55.489 [main] DEBUG example.MapperTest.selectTableNameMapById - ==> Preparing: SELECT table_name,operate_type FROM testTable WHERE id = 1
19:23:55.549 [main] DEBUG example.MapperTest - ==> Parameters:
19:23:55.603 [main] DEBUG example.MapperTest - <== Total: 1
{"operateType":"UPDATE","tableName":"med_info_shop"}
可以看到map的key是operateType和tableName,已经从下划线转成了驼峰