Mybatis-plus: mybatis plus TableField typehandler 问题

Created on 13 Jun 2018  ·  20Comments  ·  Source: baomidou/mybatis-plus

# 问题描述:
查询的时候,如果用mybatis mapper 配置返回的查询,typehandler会起作用,但是用ServiceImpl(mybatis plus 的类)的selecrtById(其实任何查询方法都可以),那么TableField 配置的TypeHandler就不起作用,看如下代码。
# 代码:
JAVA代码判断
@TableField(el = "images, typeHandler=com.zyzc.xyzy.config.db.JsonTypeHandler")
private List images;

Mybatis XML代码片段
typeHandler="com.zyzc.xyzy.config.db.JsonTypeHandler"/>

# 原因分析
我跟踪代码的时候发现了这一点。就是在在用ServiceImpl的selectById的时候。
执行到mybatis的DefaultResultSetHandler的 typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName)) 这个方法的时候,返回的是false。这个方法里面又去比较的是 TypeHandlerRegistry的 TYPE_HANDLER_MAP 这个集合比较的。而且是用的java.util.list这个类去找的。确实没找到。。但是为什么 mybatis 那种可以。。因为时间关系,我就没往下看了。。

# 结论
我认为我这个问题可能要么就是我配置错了(TableFiled上面),要么就是MybatisPlus的一个BUG。

Most helpful comment

@TableName(value = "project",autoResultMap = true)
加上autoResultMap可以了!

typeHandlersPackage倒是无所谓加不加

All 20 comments

# 补充一下
奇怪的是插入的时候typehandler 又是生效的,,就是 查询的时候 无效。

查询的 sql 你打印下看看,我们 源码测试用例里面有一个 typeHandler 的例子你可以参考下

遇到同样的问题,打印的SQL没有问题,我认为是MybatisPlus的BUG

在@TableField中指定typeHandler,所有的BaseMapper的查询相关方法都不会生效.但又无法在BaseMapper指定ResultMap.求帮助.

遇到同样的问题,插入更新没问题,查询的时候使用了默认的handler

写 resultMap,TableName注解指定该 resultMap

@spencexu 那最后你怎么解决这个问题,能否指点一下,谢谢

@ynFatal TableField和resultMap都配置了typeHandler,一个处理查询一个处理更新,测试了一下,确实是可以的

这个问题,还没有修复,最新版 3.1.2

see
https://mp.baomidou.com/config/#typehandlerspackage

在配置文件中添加配置
mybatis-plus:
typeHandlersPackage:

@TableName(value = "project",autoResultMap = true)
加上autoResultMap可以了!

typeHandlersPackage倒是无所谓加不加

@miemieYaho 如果是自定义SQL的话,这个问题仍然存在,加上@TableName(autoResultMap = true)也没用,只能自己加ResultMap

本来就这样的

@miemieYaho OK,知道不能那么用就放心了,但不是很理解为什么不能……

因为芯是mybatis

在MyBatis DefaultSetResult 这个处理类的typehandler管理中,没有发现@TableField中的typehandler被注入因此我选择手动遍历MP的@TableField注解,并且自行注入

这里说明一下
1,ClassUtil是包扫描工具,基于hutool,自行依赖
2,先扫描了注解@TableName进行定位然后在扫描@TableField,所以类需要有注解。

private void initMybatisTypeHandler(ApplicationReadyEvent event){
        SqlSessionFactory sqlSessionFactory = event.getApplicationContext().getBean(SqlSessionFactory.class);
        ClassUtil.scanPackageByAnnotation("com.xxx.xxx", TableName.class).forEach(clazz->{
            for(Field filed : clazz.getDeclaredFields()){
                TableField tableName = filed.getAnnotation(TableField.class);
                if(null != tableName && !tableName.typeHandler().equals(UnknownTypeHandler.class)){
                    sqlSessionFactory.getConfiguration().getTypeHandlerRegistry().register(filed.getType(), tableName.typeHandler());
                }
            }
        });
    }

see
https://mp.baomidou.com/config/#typehandlerspackage

在配置文件中添加配置
mybatis-plus:
typeHandlersPackage:

感谢,通过修改这个配置文件确实可以

按理配置 mybatis-plus.typeHandlersPackage=xxx, 会注入MybatisPlusProperties 然后会在MybatisPlusAutoConfiguration中设置MybatisSqlSessionFactoryBean 中的typeHandlersPackage,但是调试的时候("com.baomidou:mybatis-plus-boot-starter:2.3.1"),这个配置是不起作用的, MybatisSqlSessionFactoryBean中使用typeHandlersPackage的时机早于MybatisPlusProperties的初始化,所以可以在MybatisSqlSessionFactoryBean配置中直接注入typeHandlersPackage

按理配置 mybatis-plus.typeHandlersPackage=xxx, 会注入MybatisPlusProperties 然后会在MybatisPlusAutoConfiguration中设置MybatisSqlSessionFactoryBean 中的typeHandlersPackage,但是调试的时候("com.baomidou:mybatis-plus-boot-starter:2.3.1"),这个配置是不起作用的, MybatisSqlSessionFactoryBean中使用typeHandlersPackage的时机早于MybatisPlusProperties的初始化,所以可以在MybatisSqlSessionFactoryBean配置中直接注入typeHandlersPackage

如何在MybatisSqlSessionFactoryBean配置中直接注入typeHandlersPackage?

在MyBatis DefaultSetResult这个处理类的typehandler管理中,没有发现@TableField中的typehandler被注入因此我选择手动遍历MP的@TableField注解,并且自行注入

这里说明一下
1,ClassUtil是包扫描工具,基于hutool,自行依赖
2,先扫描了注解@TableName进行定位然后在扫描@TableField,所以类需要有注解。

private void initMybatisTypeHandler(ApplicationReadyEvent event){
        SqlSessionFactory sqlSessionFactory = event.getApplicationContext().getBean(SqlSessionFactory.class);
        ClassUtil.scanPackageByAnnotation("com.xxx.xxx", TableName.class).forEach(clazz->{
            for(Field filed : clazz.getDeclaredFields()){
                TableField tableName = filed.getAnnotation(TableField.class);
                if(null != tableName && !tableName.typeHandler().equals(UnknownTypeHandler.class)){
                    sqlSessionFactory.getConfiguration().getTypeHandlerRegistry().register(filed.getType(), tableName.typeHandler());
                }
            }
        });
    }

请问这个方法什么时候执行呢,没有找到

Was this page helpful?
0 / 5 - 0 ratings