对mybatis的Handler 从使用角度介绍
最近在开发中,涉及到了讲数据库查询的类型,直接转为java需要的类型。 由于对handler 理解不到位 和 使用不当。躺了一些坑。
主要涉及的有2种。
1、varchar 转 List<T>
2、varchar 转Map<T>
如图是写的两个handler。
ListTypeHandler 为了保证 handler的通用性,采取了 将mybatis xml 配置中的type,传入 ListTypeHandler 中直接使用。 后来发现这是个大坑。
public class ListTypeHandler<E> extends BaseTypeHandler<List<E>> {
private Class<E> type;
public ListTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<E> parameter, JdbcType jdbcType) throws SQLException {
String x = JSON.toJSONString(parameter);
ps.setString(i, x);
}
@Override
public List<E> getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return StringUtils.isBlank(s) ? null : JSON.parseArray(s, type);
}
@Override
public List<E> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return StringUtils.isBlank(s) ? null : JSON.parseArray(s, type);
}
@Override
public List<E> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return StringUtils.isBlank(s) ? null : JSON.parseArray(s, type);
}
}
public class MapTypeHandler extends BaseTypeHandler<Map<String, Object>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Map<String, Object> parameter, JdbcType jdbcType) throws SQLException {
if(MapUtils.isNotEmpty(parameter)) {
String x = JSON.toJSONString(parameter);
ps.setString(i, x);
}else{
ps.setString(i, null);
}
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return StringUtils.isBlank(s) ? null : JSON.parseObject(s, new TypeReference<Map<String, Object>>(){}); // JSON.parseObject(s, getRawType());
}
@Override
public Map<String, Object> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return StringUtils.isBlank(s) ? null : JSON.parseObject(s, new TypeReference<Map<String, Object>>(){});
}
@Override
public Map<String, Object> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return StringUtils.isBlank(s) ? null : JSON.parseObject(s, new TypeReference<Map<String, Object>>(){});
}
}
首先没有在mybatis.xml 总注册,直接通过@result指定使用
@Select("<script>SELECT " + SELECT_FILEDS_AS + " FROM " + TABLE + " WHERE valid =1 and config_id = #{configId} " + SELECT_LIMIT + " </script>")
@Results(value={
@Result(column="operation_content", property="operationContent", javaType=String.class, jdbcType=JdbcType.VARCHAR,typeHandler=ListTypeHandler.class),
})
List<OperateRecord> selectList(@Param("configId") long configId,@Param("offset") int offset,@Param("limit") int limit);
由于希望 ListTypeHandler 可以通用一点,因此采用了传入的javaType 即String,使用, 这个时候查询也没问题。感觉还很完美。
接下来,开始写插入
@Insert({"INSERT INTO " + TABLE + " (config_id, operation_staff, operation_time, action, operation_content, ctime,valid) values "
+"( #{configId}, #{operationStaff}, #{operationTime}, #{action}, #{operationContent, javaType=String, jdbcType=VARCHAR,typeHandler=ListTypeHandler}, unix_timestamp(),1 )"})
int insert(OperateRecord record);
这个时候就开始各种报错,最后经过一顿百度,发现是没有注册,于是增加注册。
<typeHandlers>
<typeHandler handler="com.support.ListTypeHandler" javaType="List" jdbcType="VARCHAR" />
</typeHandlers>
这个时候,在插入,发现成功了。 这个时候,认为全部搞定了,开始部署线下,进行联调。结果最大的问题才刚刚开始。
后头测试查询的时候,发现查询又报错。。。 于是开始debug,发现 'name' 类型varchar,java类型 String。 也开始进入list转换。 一脸懵逼。
于是尝试性的去掉字段的别名,发现居然成功了。。。
然后开始进入另一个大坑。认为和别名有关。
进入下一步的尝试
@Result(column = "initiateName" ,property = "initiateName")
为字段指定result,发现问题完美解决。
这个时候,任务只要@Results(value={}),使用过handler的,其他字段就也要指定。
这个时候,终于认为大功告成,结果。。。。
测试另一个dao的时候,发现,这个dao完全没有使用handler, 查询结果中的字段,也会去转换。。
然后,又开始懵逼。。。 一顿百度,最终恍然大悟。 再mybatisxml配置之后,是全局匹配。
因为不能使用传入的java类型, 再listhandler写死。
结论:
1.查询时候,不需要注册,即可直接通过result使用。type指定也可以生效。
2.插入的时候必须注册。
3.注册后,通过java,jdbc类型,还有名字全局匹配
4.result中可以不写,自动匹配
对mybatis的Handler 从使用角度介绍的更多相关文章
- MyBatis 3.5.2 新特性介绍
1.MyBatis 最新版本 3.5.2 发布 MyBatis最新版本是:3.5.2,发布时间是:2019年7月15日 2.MyBatis 3.5.2 新特征介绍 我们知道,MyBatis 是支持定制 ...
- MyBatis常用对象SqlSessionFactory和SqlSession介绍和运用
学习框架一个比较好的路径阅读源码.本文介绍的SqlSessionFactory和SqlSession.可以通过了解SqlSessionFactory接口和SqlSession接口以及两个的实现类入手, ...
- MyBatis执行流程的各阶段介绍
目录 一.mybatis极简示例 1.1 创建mybatis配置文件 1.2 创建数据库表 1.3 创建javabean 1.4 创建mapper映射文件 1.5 运行测试 二.mybatis的几大“ ...
- Android Bundle、Handler和Message类介绍
Bundle是一个载体,可以存放基本数据类型.对象等内容,相当于一辆汽车,可以装载很多东西,然后运到需要的地方,例如: Bundle mBundle=new Bundle(); mBundle.put ...
- Handler的简单使用介绍
Handler在android程序开发中使用的非常频繁.我们知道android是不允许在子线程中更新UI的,这就需要借助Handler来实现,那么你是否想过为什么一定要这个这样子做呢?而且Handle ...
- mybatis学习(十)——缓存介绍
与Hibernate一样,MyBatis 也提供了一级缓存和二级缓存的支持. 1.一级缓存:(本地缓存)SqlSession级别的缓存,默认一直开启的 , 与数据库同一次会话期间的数据会放到本地缓存中 ...
- Mybatis逆向工程文件标签的详细介绍:
?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUB ...
- Mybatis核心配置文件中的标签介绍
0. 标签顺序 Mybatis核心配置文件中有很多标签,它们谁谁写在前写在后其实是有顺序要求的: 从前到后: properties?,settings?,typeAliases?,typeHandle ...
- Mybatis(二):Mybatis的映射文件sqlmapper详解
MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JDBC 代码来比较,你会发现映射文件节省了大约 ...
随机推荐
- Mac下安装SecureCRT并激活
今天花了好长的时间终于把SecureCRT安装成功了 现在分享给大家 安装的步骤, 希望对大家用帮助 Mac下的SecureCRT需要破解才能使用 所以有些费劲的.. 先下载SecureCRT和破解文 ...
- 软件工程实践助教每周小结 < 福州大学 | 傅明建 >
第一周助教小结 1. 助教博客链接: http://www.cnblogs.com/sinceway/ 2. 本周点评的作业数量:约22份,有多次交互 3. 本周点评有困难的作业链接: https:/ ...
- 通过宝塔webhook,实现git自动拉取服务器代码
1.宝塔安装webhook,添加一条记录,脚本内容为: #!/bin/bash echo "" #输出当前时间 date --date='0 days ago' "+%Y ...
- 20190410Linux中磁盘管理及LVM(week2day1)
Linux磁盘管理及LVM讲解(week2_day2) 硬盘接口 从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接 ...
- 基于ROS完成寻迹运动
安装opencv功能包: $ sudo apt-get install ros-indigo-version-opencv libopencv-dev python-opencv 检测指示线: #! ...
- axure原型设计
在上一个学期的学习中,我们已经初步学习了axure的使用方法,它可以为负责定义需求设计,功能和界面的人员能快速设计出所需产品. 引入:在我们想为软件设计原型的时候,纸质原型很难表达交互的界面,与此同时 ...
- 输入时间参数获取rds备份集信息
1.脚本 [root@localhost tmp]# more geturl_test.py #!/usr/bin/env python #coding=utf- import os, json, u ...
- cookie的存入和取出
刚刚开始写页面没多久,因为登录注册写的是个tab切换,所以需要在点击登录的时候跳到登录页面,点击注册的时候跳转到注册页面,自己在网上找了一下,研究了一下cookie方法,现在把它记下来. 存入cook ...
- GIT命令介绍
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下. 区别与集中式的分布式实现!!!! 集中 ...
- SpringBoot和druid数据源集成Jpa
1.pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...