今天在使用mybatis查詢時遇到報錯
Error attempting to get column 'e_gender' from result set. Cause: java.sql.SQLException: Cannot convert value '男' from column 3 to TIMESTAMP.
; Cannot convert value '男' from column 3 to TIMESTAMP.; nested exception is java.sql.SQLException: Cannot convert value '男' from column 3 to TIMESTAMP.
在網上查了很多解決辦法,大多都是說是數據庫字段類型與實體類的屬性類型的定義不一致的原因,但是請看:
<resultMap type="com.xyw.hospital.model.entity.Employee" id="BaseMap">
<result property="eId" column="e_id" jdbcType="INTEGER"/>
<result property="eName" column="e_name" jdbcType="VARCHAR"/>
<result property="eGender" column="e_gender" jdbcType="VARCHAR"/>
<result property="eBirthday" column="e_birthday" jdbcType="TIMESTAMP"/>
<result property="eDid" column="e_did" jdbcType="INTEGER"/>
<result property="eRoleid" column="e_roleid" jdbcType="INTEGER"/>
<result property="eTel" column="e_tel" jdbcType="VARCHAR"/>
<result property="eVprice" column="e_vprice" jdbcType="NUMERIC"/>
<result property="eState" column="e_state" jdbcType="INTEGER"/>
<result property="eCreateTime" column="e_create_time" jdbcType="TIMESTAMP"/>
<result property="eClossTime" column="e_closs_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="items">
e_id, e_name, e_gender, e_birthday, e_did, e_roleid, e_tel, e_vprice, e_state, e_create_time, e_closs_time </sql>
<!--查詢單個-->
<select id="queryById" resultMap="BaseMap">
select
<include refid="items"/>
from employee
where e_id = #{eId}
</select>
CREATE TABLE `employee` (
`e_id` int(11) NOT NULL AUTO_INCREMENT,
`e_name` varchar(25) DEFAULT NULL,
`e_gender` varchar(4) DEFAULT NULL COMMENT '''男''或''女''',
`e_birthday` date DEFAULT NULL,
`e_did` int(11) DEFAULT NULL,
`e_roleid` int(11) DEFAULT NULL,
`e_tel` varchar(15) DEFAULT NULL,
`e_vprice` decimal(10,2) DEFAULT NULL,
`e_state` int(1) DEFAULT '0' COMMENT '0 新注冊(默認) 1 在職 2離職',
`e_create_time` date DEFAULT NULL,
`e_closs_time` date DEFAULT NULL,
PRIMARY KEY (`e_id`) USING BTREE,
KEY `idx_did` (`e_did`) USING BTREE,
KEY `idx_roleid` (`e_roleid`) USING BTREE,
KEY `idx_state` (`e_state`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
protected Integer eId;
protected String eName;
protected String eGender;
protected Date eBirthday;
protected Integer eDid;
protected Integer eRoleid;
protected String eTel;
protected Double eVprice;
protected Integer eState;
protected Date eCreateTime;
protected Date eClossTime;
public Employee(String eName, String eGender, Date eBirthday, String eTel, Integer eDid, Integer eRoleid, Double eVprice) {
//略
}
可以看到字段定義一致,導致一致我一直不得其解。
這個地方真正的原因是什么呢?
大家也許已經看到了,我這里有個構造方法,其中省去了一個字段,導致查到的數據多余構造方法中的數據,使得其將e_id->eName,e_name->eGender,e_gender->eBirthday,這里因為e_gender是vchar,而eBirthday是date類型,導致的類型轉換失敗。
這里又回到類型問題了,關於類型轉換的問題這里不詳說。但是大家記得在定義數據庫字段與實體類字段的類型一定要一致。
而這里的問題就在於mybatis在進行賦值時會使用實體類的構造方法進行賦值,如果構造方法中的參數個數與mysql結果集中的字段數量不一致時,特別是少了前面的參數,賦值時會按照順序進行賦值,就有可能會出錯。
這里的解決辦法很簡單,只要在實體類中添加一個空的構造方法
public Employee() {
}
即可,mybatis會優先使用最適合的構造方法進行賦值,如果找不到適合的構造方法,就會使用空的構造方法,在賦值時會從實體類的屬性中查找與結果集中字段名相同的屬性進行賦值。
這讓我想起以前在剛學習javaweb時老師總是強調空的構造方法的重要性,卻始終不能理解,這次的出錯讓我記得以后對於pojo類的定義時,如果需要定義有參的構造方法,一定要把無參構造方法給補上,防止出現類似問題。
以上都是本人自己的理解,可能會與真正的解答不一致,歡迎各位大佬指正。
