最近在开发中,涉及到了讲数据库查询的类型,直接转为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 从使用角度介绍的更多相关文章

  1. MyBatis 3.5.2 新特性介绍

    1.MyBatis 最新版本 3.5.2 发布 MyBatis最新版本是:3.5.2,发布时间是:2019年7月15日 2.MyBatis 3.5.2 新特征介绍 我们知道,MyBatis 是支持定制 ...

  2. MyBatis常用对象SqlSessionFactory和SqlSession介绍和运用

    学习框架一个比较好的路径阅读源码.本文介绍的SqlSessionFactory和SqlSession.可以通过了解SqlSessionFactory接口和SqlSession接口以及两个的实现类入手, ...

  3. MyBatis执行流程的各阶段介绍

    目录 一.mybatis极简示例 1.1 创建mybatis配置文件 1.2 创建数据库表 1.3 创建javabean 1.4 创建mapper映射文件 1.5 运行测试 二.mybatis的几大“ ...

  4. Android Bundle、Handler和Message类介绍

    Bundle是一个载体,可以存放基本数据类型.对象等内容,相当于一辆汽车,可以装载很多东西,然后运到需要的地方,例如: Bundle mBundle=new Bundle(); mBundle.put ...

  5. Handler的简单使用介绍

    Handler在android程序开发中使用的非常频繁.我们知道android是不允许在子线程中更新UI的,这就需要借助Handler来实现,那么你是否想过为什么一定要这个这样子做呢?而且Handle ...

  6. mybatis学习(十)——缓存介绍

    与Hibernate一样,MyBatis 也提供了一级缓存和二级缓存的支持. 1.一级缓存:(本地缓存)SqlSession级别的缓存,默认一直开启的 , 与数据库同一次会话期间的数据会放到本地缓存中 ...

  7. Mybatis逆向工程文件标签的详细介绍:

    ?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUB ...

  8. Mybatis核心配置文件中的标签介绍

    0. 标签顺序 Mybatis核心配置文件中有很多标签,它们谁谁写在前写在后其实是有顺序要求的: 从前到后: properties?,settings?,typeAliases?,typeHandle ...

  9. Mybatis(二):Mybatis的映射文件sqlmapper详解

    MyBatis 真正的力量是在映射语句中.这里是奇迹发生的地方.对于所有的力量,SQL 映射的 XML 文件是相当的简单.当然如果你将它们和对等功能的 JDBC 代码来比较,你会发现映射文件节省了大约 ...

随机推荐

  1. DLG消息

    WM_GETMINMAXINFO 0X0024 WM_NCCREATE 0X0081 WM_NCCALCSIZE 0X0083   WM_CREATE 0X0001 WM_SIZE 0X0005 WM ...

  2. Vuex 2.0 深入简出

    最近面试充斥了流行框架Vue的各种问题,其中Vuex的使用就相当有吸引力.下面我就将自己深入简出的心得记录如下: 1.在vue-init webpack project (创建vue项目) 2.src ...

  3. vi / vim 命令集合

    vim的命令太多了,不常用就会忘记,所以我决定把vim的各种命令整理下来,包括vim的插入删除.光标移动.多窗口编辑.复制粘贴.查找替换.以及一些常用命令 删除操作 dd 删除当前行 ndd      ...

  4. 福州大学软件工程1916|W班 第2次作业成绩排名

    作业链接: 结对第一次-原型设计(文献摘要热词统计) 评分准则: 本次作业评分分为两部分,一部分是博客分数(满分25分),另一部分是工程能力分数(满分30分). 博客分数评分标准: 1.在随笔开头请加 ...

  5. 自己动手写java锁

    1.LockSupport的park和unpark方法的基本使用,以及对线程中断的响应性 LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语.java锁和同步器 ...

  6. python学习之文本文件上传

    最近用python的flask框架完成了一个最基本的文本文件上传,然后读取. 前端用的Angular的ng2-file-upload完成文件上传,后端用flask接收上传的文件,接着做处理. 在交互的 ...

  7. Centos 7 安装 ELK 5.6.8 及基础的配置

    下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.8.rpm wget https://ar ...

  8. CentOS 7离线安装CDH 5.16.1完全指南(含各种错误处理)

    安装包下载 1.CM软件包下载 从http://archive.cloudera.com/cm5/redhat/7/x86_64/cm/5.16.1/RPMS/x86_64/下载rpm包,如下: 其实 ...

  9. 翻译 | Placing Search in Context The Concept Revisited

    翻译 | Placing Search in Context The Concept Revisited 原文 摘要 [1] Keyword-based search engines are in w ...

  10. python面对对象

    面对过程VS面对对象 面向过程的程序设计的核心是过程,过程就是解决问题的步骤,面向过程的设计就是考虑周全什么时候处理什么东西 优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可. ...