首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis "invalid types" 錯誤排查:構造方法、Getter/Setter 與類型不匹配

     編輯:Java 綜合教學

錯誤現象

Cause: org.apache.ibatis.reflection.ReflectionException: 
Error instantiating class cn.qd.mybatis.pojo.User with invalid types (Integer,String,String) ...

根因分析

MyBatis 結果映射時,預設調用**無參構造器**創建對象,再透過 **Setter** 注入屬性。若存在帶參構造器且參數類型與查詢欄位順序/類型匹配,MyBatis 可能誤以為是構造器注入模式,導致類型不匹配。

三大常見原因與解決

1. Getter/Setter 與成員變數不一致

// 錯誤:欄位名 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")
})

2. 構造方法被重載,參數類型需為包裝類型

// 錯誤:基本類型 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) { ... }

3. 避免基本類型,統一使用包裝類型

// 實體類屬性建議
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 + '\'' + "}";
    }
}

Mapper XML 結果映射對照

<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>

進階:構造器注入模式 (MyBatis 3.4.3+)

<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) { ... }

排查檢查清單

  1. 實體類是否有無參構造器?
  2. 屬性是否為包裝類型 (Integer/Long/Boolean)?
  3. Getter/Setter 命名是否標準駝峰?
  4. 是否開啟 mapUnderscoreToCamelCase?
  5. 結果映射 resultMap 類型/屬性/欄位是否對應?
  6. 查詢 SQL 欄位順序/別名是否與映射一致?

總結

MyBatis "invalid types" 核心在於**構造器參數類型與映射邏輯不匹配**。遵循「無參構造器 + 包裝類型屬性 + 標準 Getter/Setter + 駝峰映射」慣例,可避免 90% 此類問題。若需構造器注入,請顯式配置 <constructor> 並確保參數類型完全一致。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved