Cause: org.apache.ibatis.reflection.ReflectionException:
Error instantiating class cn.qd.mybatis.pojo.User with invalid types (Integer,String,String) ...
MyBatis 結果映射時,預設調用**無參構造器**創建對象,再透過 **Setter** 注入屬性。若存在帶參構造器且參數類型與查詢欄位順序/類型匹配,MyBatis 可能誤以為是構造器注入模式,導致類型不匹配。
// 錯誤:欄位名 userName,Setter setUserName,但資料庫欄位 user_name
private String userName;
public void setUserName(String name) { ... } // 駝峰 vs 下劃線
// 解決:開啟駝峰映射或使用 @Result 手動映射
// mybatis-config.xml
<setting name="mapUnderscoreToCamelCase" value="true"/>
// 或 Mapper 介面
@Results({
@Result(property = "userName", column = "user_name")
})
// 錯誤:基本類型 int 導致類型匹配失敗
public User(int id, String name, String email) { ... }
// 正確:使用包裝類型 Integer
public User(Integer id, String name, String email) { ... }
// 最佳:保留無參構造器,MyBatis 優先使用無參 + Setter
public User() {}
public User(Integer id, String name, String email) { ... }
// 實體類屬性建議
private Integer id; // 而非 int
private Long userId; // 而非 long
private Boolean active; // 而非 boolean
private Double score; // 而非 double
// 原因:
// 1. 基本類型無法表示 null (資料庫 NULL)
// 2. MyBatis 類型處理器對包裝類型支援更完善
// 3. 避免構造器注入時基本類型默認值干擾
public class User implements Serializable {
private static final long serialVersionUID = 1L;
// 包裝類型屬性
private Integer id;
private String username;
private String email;
private Integer age;
private Boolean enabled;
private Date createTime;
// 無參構造器 (MyBatis 必需)
public User() {}
// 業務構造器 (包裝類型參數)
public User(Integer id, String username, String email) {
this.id = id;
this.username = username;
this.email = email;
}
// 標準 Getter/Setter (駝峰命名)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
// ... 其他省略
// toString 方便除錯
@Override
public String toString() {
return "User{id=" + id + ", username='" + username + '\'' + "}";
}
}
<resultMap id="userMap" type="com.xxx.pojo.User">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="age" column="age" jdbcType="INTEGER"/>
<result property="enabled" column="enabled" jdbcType="BIT"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
<select id="selectById" resultMap="userMap">
SELECT id, username, email, age, enabled, create_time
FROM sys_user WHERE id = #{id}
</select>
<resultMap id="userMap" type="com.xxx.pojo.User">
<constructor>
<idArg column="id" javaType="Integer" jdbcType="INTEGER"/>
<arg column="username" javaType="String" jdbcType="VARCHAR"/>
<arg column="email" javaType="String" jdbcType="VARCHAR"/>
</constructor>
</resultMap>
-- 實體類需對應構造器
public User(Integer id, String username, String email) { ... }
mapUnderscoreToCamelCase?resultMap 類型/屬性/欄位是否對應?MyBatis "invalid types" 核心在於**構造器參數類型與映射邏輯不匹配**。遵循「無參構造器 + 包裝類型屬性 + 標準 Getter/Setter + 駝峰映射」慣例,可避免 90% 此類問題。若需構造器注入,請顯式配置 <constructor> 並確保參數類型完全一致。