為了減少mybatis手寫xml的代碼量和出錯率,我使用了tk-mybatis通用mapper拯田。具體過程可以參考SpringBoot集成tk.mybatis
然鵝,通用mapper只是實現(xiàn)了常用SQL操作,對于一些復雜操作或者效率要求高的操作實現(xiàn)起來卻很不方便侣监,所以想著可以結(jié)合xml來擴展這些復雜SQL臣淤。
根據(jù)http://www.reibang.com/p/50449dde7f2b配置好了擴展xml橄霉。但是我不想在xml中定義繁瑣的resultMap來定義數(shù)據(jù)庫字段和javabean字段的映射關(guān)系邑蒋,這樣不僅修改起來繁瑣,而且很容易出錯医吊,我想使用JavaBean或者數(shù)據(jù)庫實體類Entity來定義resultMap,再結(jié)合單元測試束莫,完美。
如下是表sql
CREATE TABLE `subscribe` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`user_id` bigint(20) default NULL COMMENT '訂閱者用戶id',
`type` INT default NULL COMMENT '訂閱類型',
`subordinate` varchar(64) default NULL COMMENT '所屬',
`trigger_type` INT DEFAULT NULL COMMENT '觸發(fā)條件類型',
`trigger_value` INT DEFAULT NULL COMMENT '觸發(fā)值',
`create_time` DATETIME default CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`publish_time` DATETIME DEFAULT NULL COMMENT '發(fā)布時間',
`last_publish_time` DATETIME DEFAULT NULL COMMENT '上一次發(fā)布時間',
`publish_frequency` INT DEFAULT NULL COMMENT '發(fā)布頻率',
`delete_time` DATETIME default null COMMENT '刪除時間',
`is_deleted` BOOLEAN default false COMMENT '刪除',
PRIMARY KEY (`id`),
INDEX subscribe_user_id(user_id),
INDEX subscribe_publish_time(publish_time)
) ENGINE=InnoDB;
insert into subscribe (user_id, type, subordinate, trigger_type, trigger_value, publish_time, publish_frequency)
values (1, 0, 110101, 0, 0, '2019-05-27 07:50:00', 0);
insert into subscribe (user_id, type, subordinate, trigger_type, trigger_value, publish_time, publish_frequency)
values (1, 0, 110101, 0, 1, '2019-05-27 07:50:00', 0);
如下是JavaBean
package com.eee.subscribe.domain;
import lombok.Builder;
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
@Data
@Builder
@Table(name = "subscribe")
public class Subscribe implements Serializable {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private Long userId;
private SubscribeType type;
private String subordinate;
private TriggerType triggerType;
private TriggerValue triggerValue;
private Date createTime;
private Date publishTime;
private Date lastPublishTime;
private PublishFrequency publishFrequency;
private Date deleteTime;
@Column(name = "is_deleted")
private boolean deleted;
}
如下是mapper
@Mapper
@Component
interface SubscribeMapper extends BaseMapper<Subscribe, Long> {
Subscribe selectById(Long id);
}
如下是mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.eee.subscribe.dao.SubscribeMapper">
<select
id="selectById"
parameterType="java.lang.Long"
resultType="com.eee.subscribe.domain.Subscribe">
SELECT * FROM
subscribe
WHERE id = #{id};
</select>
</mapper>
但是執(zhí)行測試報錯了:
org.springframework.dao.DataIntegrityViolationException: Error attempting to get column 'SUBORDINATE' from result set. Cause: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "nqghMS" [22018-199]
; Data conversion error converting "nqghMS" [22018-199]; nested exception is org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "nqghMS" [22018-199]
后來我又打開了mapUnderscoreToCamelCase奇昙。但報錯還是依舊蒋譬。我甚至懷疑是mapUnderscoreToCamelCase沒有生效揍诽,然鵝打開SpringBoot監(jiān)控后發(fā)現(xiàn)此選項確實打開了栗竖。
mybatis.configuration.mapUnderscoreToCamelCase=true
最終發(fā)現(xiàn)是因為框架內(nèi)映射代碼選擇字段和字段所屬類時竟然有錯誤暑脆。如下圖框架代碼所示狐肢,取Subscribe表的type字段時,columnName是type份名,但parameterType并不是對應(yīng)的SubscribeType類型,而是String類型僵腺,導致選擇了錯誤的typeHandler,最后解析值錯誤了......
不知道這是為啥普监,但解決方法被我猜了了,就是實體映射JavaBean類的字段順序要和建表的字段順序相同凯正,而且mapUnderscoreToCamelCase開不開啟也沒影響。
很奇怪的一個bug......