MyBatis的若干问题总结二
1.排序问题
这里的问题我其实是想ORDER BY后面的子句,传入一个动态的,比如可能是:ORDER BY RecordTime ASC
,或者是ORDER BY SiteNo ASC
,但是向下面的问题,就会出现错误。
1 | SELECT * FROM lsmfhx.v_realtime WHERE SiteNo in |
Syntax error: failed at position 343 (line 9, col 22): ‘ASC’ LIMIT 0,100 FORMAT TabSeparatedWithNamesAndTypes;
根据资料显示:
(1)对于形如#{variable} 的变量,Mybatis会将其视为字符串值,在变量替换成功后,缺省地给变量值加上引号。"variable"
(2)对于形如${variable}的变量,Mybatis会将其视作直接变量,即在变量替换成功后,不会再给其加上引号。
2.动态字段名
需求的含义是,我可以查询一个字段,也可能查询两个字段,比如:
1 | ## 查询一个字段 |
一个语句中,我可能只查询姓名一个字段,而另一语句中我想查询姓名和年龄两个字段,如果单独写两个语句,我又觉得不合适,所以就有了动态字段的问题。
(1) 添加:statementType=”STATEMENT”
1 | <select id="getChartArr" resultType="Map" statementType="STATEMENT"> |
(2) 将#{fieldlist}换为${fieldlist}
(3) 编写mapper
1 | List<Map> getChartArr(String fieldlist,String startdate,String enddate,Integer mediumtype,Integer siteno); |
(4) 在必要的时候给变量添加单引号,比如上面语句中的start_time和end_time
1 | String filedlist="InsFlux,DifPress"; |
因为最后编译成的sql语句类似如下内容
1 | SELECT InsFlux,DifPress,RecordTime FROM lsmfhx.v_realtime where parseDateTimeBestEffortOrNull(RecordTime) |
如果不加单引号就会变成:
1 | SELECT InsFlux,DifPress,RecordTime FROM lsmfhx.v_realtime where parseDateTimeBestEffortOrNull(RecordTime) |
sql语句就不对了。
3.无法给带下划线的的属性赋值
在使用mybatis的时候,遇到了一个奇怪的问题,有些字段从数据库中取出都是null,但是数据库中明明是有值的,比如issue_time,比如class_type。当然也是不所有的内容都是空的,比如application_job就不是空的,后来呢。我想到了, class_type是int类型,但是application_job是VARCHAR类型,会不会是这个数据类型的问题呢?所以就有两种解决方法,通俗的方法一种是将带下划线的数据类型变成String类型或者是将下划线去掉,当然这也不是长久之计。
比如下面的sql语句,如果将结果转换成 List<Map<String,Object>> 数组,理论上每一个Map都应该包含五个属性 last_sum_flux、last_sum_heat、SumFlux、RecordTime、SiteNo,但是结果却只有SumFlux、RecordTime和SiteNo这几个属性,我尝试修改了SiteNo改为Site,结果也还是一样,在返回的结果中有Site字段,却没有last_sum_flux字段和last_sum_heat字段。
1 | <select id="getDailySumFlux" resultType="java.util.HashMap"> |
至于参考文章中的方法,还没有测试。而且就算是我修改了application的配置,似乎还是没有效果,无论我选择 map-underscore-to-camel-case 是 true 还是 false,都无济于事。奇怪的是,同样的代码,不同的数据库,竟然也会有差别,我就真是看不出来到底有什么区别了。
【解决方法】
经过尝试,我终于发现了两者的区别了,一个查询的为null,另外一个数据库查询的结果last_sum_flux不为null,所以就会出现差别。
1.关闭自动驼峰映射:
1 | mybatis-plus: |
2.配置属性,将null显示
1 | mybatis-plus: |
我配置了call-setters-on-nulls,似乎不起作用,最后返回的结果Map<String,Object>,还是没有这个 last_sum_flux 字段。
1.mybatis无法给带有下划线属性赋值问题 开启 mapUnderscoreToCamelCase 自动驼峰命名
2.mybatis无法给带有下划线属性赋值问题
3.mybatis plus字段名称有下划线读取不到值的问题 map-underscore-to-camel-case: false # 数据库下划线自动转驼峰标示关闭
4.mybatis-plus返回map的一些问题 spring boot整合mybatis时,返回map中value为空导致字段不显示:mybatis-plus.configuration.map-underscore-to-camel-case=true
5.mybatis 数据库null值字段 无法映射到Map mybatis.configuration.call-setters-on-nulls=true
6.springboot+mybatis-plus接口返回map值为null的字段不显示
7.mybatis返回map类型数据空值字段不显示的解决方法
8.callSettersOnNulls 通俗的讲,即 MyBatis 在使用 resultMap 来映射查询结果中的列,如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段,这就导致在调用到该字段的时候由于没有映射,取不到而报空指针异常。
4. Cause: java.lang.IllegalArgumentException: argument type mismatch
使用到了Mybatis Plus,对于自增的字段,要使用type进行注释
1 | public class Device { |
1.mybatis 插件小bug
5.实体属性名和数据库字段名不一致时的处理
有时候如果实体属性中的字段名和数据库的字段名不一样,进行查询的时候,就会报错。
mybatis plus中有一个注解叫@Tablefield(exist = false),意思就是说,这个字段,数据库可以不存在,如果数据库不存在这个字段,不会报错,但是如果数据库中有这个字段,还会返回相应的信息吗?
经过实际的测试,添加了这个注解之后,即便是数据库中存在这个字段,那么相应的数据也不会返回了。
因为在使用 MyBatis Plus 返回相应的list()的时候,构造select语句,是使用的” select filed1,filed2 from table”这种形式,而不是”select * from table”的形式,所以需要自定义select语句
1 | public interface MediumMapper extends BaseMapper<Medium> { |
或者是在使用查询语句的时候,指定select语句
1 | QueryWrapper<VClient> queryWrapper=new QueryWrapper<>(); // 查询条件 |
1.Mybatis 当实体属性与数据库字段不一致时的解决方案 (这篇文章其实还是有用的,就是说要采用resultMap的方式处理实体类和字数据库字段不一致的情况)
2.MyBatis之实体类属性与表字段不一致的处理
3.程序员,Mybatis 你踩过坑吗? (Mybatis的一些使用案例)
4.mybatis动态调用表名和字段名 (动态字段名,其实和我的需求有点像)
5.使用Mybatisplus中的selectMaps方法返回值字段为空不显示的问题 (这里有一个叫selectMaps的方法,可以自定义返回的字段,这里还提到了一个属性配置,就是call-setters-on-nulls,设置为true之后,即便数据库中的字段是null的,也会返回相应的字段)
6.java object互转Map的三种方法
7.MyBatis-Plus 自定义sql语句
6.Could not set parameters for mapping: ParameterMapping
7.invalid comparison: java.util.Date and java.lang.String
在使用若依自动生成的代码进行增加操作之后,出现了这个问题。本来我以为是数据类型的问题,把网上找的sql代码的数据类型,java中的Date类型,对应的数据库类型改为了datetime,之后还是不行。
【解决方法】
去掉为空的判断就可以了。
1 | <!--错误--> |
1.mybatis异常invalid comparison: java.util.Date and java.lang.String 原工程中配置的是mybatis-3.2.8, 而我测试工程中用的是mybatis-3.3.0.后来在网上找了一下才知道, 原来这是mybatis 3.3.0中对于时间参数进行比较时的一个bug. 如果拿传入的时间类型参数与空字符串’’进行对比判断则会引发异常. 所以在上面的代码中去该该判断, 只保留非空判断就正常了。
8.Invalid value type for attribute ‘factoryBeanObjectType’: java.lang.String
这是在使用 mybatis 的时候出现的问题,因为我用了 mybatis-plus-boot-starter,所以他依赖的 底层的 mybatis 比较老。
【解决方案】
自行解决,或者将 mybatis-plus-boot-starter 改为 mybatis-plus-spring-boot3-starter
1 | <dependency> |
后来又遇到了 :“Bean named ‘ddlApplicationRunner’ is expected to be of type ‘org.springframework.boot.Runner’ but was actually of type ‘org.springframework.beans.factory.support.NullBean’”,只能通过 升级 mybatis-plus-boot-starter版本解决
【1】.springboot由3.1.5升级到3.2.0 报Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String 这里讲了三种方法,一种就是降级,还有就是升级 mybatisplus,最后就是自己解决。
【2】.Bean named ‘ddlApplicationRunner’ is expected to be of type ‘org.springframework.boot.Runner’ but was actually of type ‘org.springframework.beans.factory.support.NullBean’
【3】.SpringBoot 3.2.1 启动报错