MyBatis自动转型tinyint(1)为boolean及Integer=0处理成空字符问题

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 MyBatis自动转型tinyint(1)为boolean及Integer=0处理成空字符问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

背景

数据表定义:

create table timed_task (
    id                  bigint unsigned auto_increment comment 'PK' primary key,
    task_status         tinyint(1) default 0                 not null comment '任务状态:1启用,2禁用',
    mq_switch           tinyint(1) default 0                 not null comment '是否发送消息至MQ:1发送,0不发送',
    isactive 			tinyint(1) default 1 				 not null comment '逻辑删除',
    inserttime          datetime   default CURRENT_TIMESTAMP not null comment '插入时间',
	insertby            varchar(100)                         null comment '创建人',
    updatetime          datetime   default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
    updateby            varchar(100)                         null comment '更新人'
) comment '定时任务配置表' collate = utf8mb4_unicode_ci;

其中有三个tinyint(1)字段。

java接口定义为:

List<Map> selectListBySelective(Map<String, Object> map);

MyBatis的mapper.xml文件定义:

<select id="selectListBySelective" parameterType="Map" resultType="Map">
    select
    tt.id,
    ifnull(tt.task_status, 0) as taskStatus,
    tt.mq_switch as mqSwitch,
    tt.inserttime,
    tt.insertby,
    date_format(tt.updatetime,'%Y-%m-%d %H:%i:%s') as updatetime,
    tt.updateby,
    ifnull(tt.isactive, 0)
    from timed_task tt
    where tt.isactive = 1
    order by tt.updatetime desc
</select>

可见,对于三个不同的tinyint(1)字段的处理方式不一样。

对于spring Boot + MyBatis 应用,在配置文件application.properties里面新增一条配置信息:logging.level.com.aaa.mapper=debug,即可实现打印输出SQL语句到日志控制台。

SQL语句如下:

select tt.id,
       ifnull(tt.task_status, 0)                       as taskStatus,
       tt.mq_switch                                    as mqSwitch,
       tt.inserttime,
       tt.insertby,
       date_format(tt.updatetime, '%Y-%m-%d %H:%i:%s') as updatetime,
       tt.updateby,
       ifnull(tt.isactive, 0)
from timed_task tt
where tt.isactive = 1
order by tt.updatetime desc

拿到SQL语句去DataGrip执行,没有问题:

id taskStatus mqSwitch inserttime insertby updatetime updateby ifnull(tt.isactive, 0)
3 1 1 2020-08-26 10:49:52 awesome 2020-08-26 10:49:52 awesome 1

但postman调用接口得到的返回数据是:

{
  "list": [
    {
      "id": 3,
      "ifnull(tt": {
        "isactive, 0)": 1
      },
      "inserttime": "1598410192000",
      "mqSwitch": true,
      "taskStatus": 1,
      "updateby": "awesome",
      "insertby": "awesome",      
      "updatetime": "2020-08-26 10:49:52",
    }
  ]
}

分析

问题1

inserttime字段是datetime类型,取值变成timestamp,除非如date_format(tt.updatetime, '%Y-%m-%d %H:%i:%s') as updatetime一样处理一下。

问题2

在返回值为Map类型(即resultType="Map")时,数据表里的tinyint(1)类型的数据(即[1, 0]),被mybatis会自动把转换成boolean类型数据(即[true/false]),参考Mybatis中tinyint(1)数据自动转化为boolean处理
解决方案:

  1. 使用ifnull(column, 0)处理该字段
  2. 在jdbcUrl添加参数:tinyInt1isBit=false(默认为true)
  3. 避免使用长度为1的tinyint类型字段存储数字格式的数据。

在笔者的问题场景下,只推荐第一种解决方案。即通过ifnull处理。因此,可以看到taskStatus如期返回1,而mqSwitch还是返回true。

问题2

isactive字段,也采用ifnull(tt.isactive, 0)加以处理,但是没有后面的as表达式部分。接口返回居然是:

"ifnull(tt": {
  "isactive, 0)": 1
},

在这里插入图片描述
备注:本文使用的MyBatis为mybatis-spring-boot-starter,版本:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.0.1</version>
    <!--升级到这个版本,还是有问题-->
    <!--<version>2.1.3</version>-->
</dependency>

对应的mybatis版本:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
    <!-- mybatis-spring-boot-starter 2.1.3 版本依赖的mybatis版本 -->
    <!--<version>3.5.5</version>-->
</dependency>

所以,在MyBatis看来,这不是问题!!??

在实体类PO里面有定义字段applyStatus,查询条件也返回t1.applyStatus,SQL执行没有问题,但是MyBatis就是不返回该数据;

ifnull(t1.applyStatus, 0) as applyStatus

问题

数据表有个表示状态的字段,类型定义为tinyint(1),1表示状态开启,0表示状态关闭,前端查询条件里有个下拉框,选择开启或者关闭,根据此状态来查询数据:

<if test="status != null and status != ''">
    AND status = #{status}
</if>

但是始终不生效,看前端传参0和1,1时查询正常,0时查询失败,说明问题不在前端。

打印SQL执行日志,发现根本没有带上AND status = 0这个条件。

此时才发现,MySQL字段定义为tinyint(1)时,MyBatis会把Integer = 0当作空字符串来处理。

因此上面的if条件不成立,解决方案:

<if test="status != null">
    AND status = #{status}
</if>

非tinyint入库失败

有如下数据表定义:

create table channel_advertiser_id (
    id                    int auto_increment primary key,
    category_id           int                                  null comment '广告主分类id',
    use_id                int                                  null comment '广告主用途id',
    isagentaccount        int(5)     default 2                 not null comment '1:代理账号 0:非代理账号 2:空',
    status                int(5)     default 1                 not null comment '投放状态 1:投放中 2:投放停止'
) charset = utf8;
create index id on kraken_pre.channel_advertiser_id (id);

可以发现这些字段都不是tinyint类型,而是int类型。

有如下MyBatis的mapper.xml

<update id="updateAdvertiserIdByParams">
    UPDATE channel_advertiser_id
    <set>
        <if test="categoryId != null and categoryId !=''">
            category_id = #{categoryId},
        </if>
        <if test="useId != null and useId !=''">
            use_id = #{useId},
        </if>
        <if test="isAgentAccount != null and isAgentAccount !=''">
            isagentaccount = #{isAgentAccount},
        </if>
        <if test="status != null and status !=''">
            status = #{status},
        </if>
    </set>
    where id = #{id}
</update>

省略数据库PO定义,用如下单元测试类来验证:

/**
 * @author johnny
 */
@RunWith(SpringRunner.class)
@springbootTest(classes = WebApplication.class)
public class MapperTest {

    @Resource
    private ChannelAdvertiserIdMapper advertiserIdMapper;

    @Test
    public void test() {
        ChannelAdvertiserId advertiser = new ChannelAdvertiserId();
        advertiser.setId(9159L);
        advertiser.setCategoryId(0);
        advertiser.setUseId(0);
        advertiser.setStatus(0);
        advertiser.setIsAgentAccount(0);
        advertiserIdMapper.updateAdvertiserIdByParams(advertiser);
    }
}

断点调试时的截图:
在这里插入图片描述
但是执行报错:

### SQL: UPDATE channel_advertiser_id                    where id = ?
### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id = 9159' at line 3

也就是说,MyBatis的and categoryId !=''条件不满足,即MyBatis将Integer类型的0处理成空字符串?!!!

解决方法:去掉if条件判断的后半部分。

参考

Mybatis中tinyint(1)数据自动转化为boolean处理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/142262.html

(0)

相关推荐

  • 企业微信通过群聊机器人用springboot发送信息

    导读:本篇文章讲解 企业微信通过群聊机器人用springboot发送信息,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年2月14日
    00
  • Mybatis动态SQL语句大全

    导读:本篇文章讲解 Mybatis动态SQL语句大全,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年2月21日
    00
  • 三天打鱼两天晒网

    导读:本篇文章讲解 三天打鱼两天晒网,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年1月25日
    00
  • c++聊天室设计数据库(3)

    追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

    导读:本篇文章讲解 c++聊天室设计数据库(3),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

    技术随笔 2023年4月2日
    00
  • 漫聊 ThreadLocal (内存泄漏,弱引用)

    有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

    导读:本篇文章讲解 漫聊 ThreadLocal (内存泄漏,弱引用),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

    技术随笔 2023年4月19日
    00
  • Day08—Http协议概述、Request

    导读:本篇文章讲解 Day08—Http协议概述、Request,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年1月29日
    00
  • Linux常见命令 25 – RPM包安装、升级、卸载、查询、校验、提取

    导读:本篇文章讲解 Linux常见命令 25 – RPM包安装、升级、卸载、查询、校验、提取,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年2月1日
    00
  • ServletConfig介绍和使用

    有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

    导读:本篇文章讲解 ServletConfig介绍和使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

    技术随笔 2023年5月29日
    00
  • 腾讯前端一面常考vue面试题汇总

    导读:本篇文章讲解 腾讯前端一面常考vue面试题汇总,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年2月8日
    00
  • eclipse修改主题或背景颜色

    导读:本篇文章讲解 eclipse修改主题或背景颜色,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

    技术随笔 2023年2月22日
    00

发表回复

登录后才能评论