在使用 MyBatis 進行資料庫操作時,實體類屬性名與資料表欄位名不一致是常見問題。本文將透過完整範例,示範如何透過 SQL 別名與 <resultMap> 兩種方式解決欄位映射不匹配的問題。
首先建立 orders 資料表並插入測試資料:
CREATE TABLE orders(
order_id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(20),
order_price FLOAT
);
INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23);
INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33);
INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);
實體類 Order 的屬性名(id、orderNo、price)與資料表欄位(order_id、order_no、order_price)並不對應:
package me.gacl.domain;
public class Order {
private int id; // 對應 order_id
private String orderNo; // 對應 order_no
private float price; // 對應 order_price
// 省略 getter/setter/toString
}
在 orderMapper.xml 中展示三種查詢方式:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="me.gacl.mapping.orderMapper">
<!-- 1. 直接查詢:因欄位名不匹配,無法封裝結果 -->
<select id="getOrderById" parameterType="int" resultType="me.gacl.domain.Order">
select * from orders where order_id=#{id}
</select>
<!-- 2. 使用 SQL 別名讓欄位名與屬性名一致 -->
<select id="selectOrder" parameterType="int" resultType="me.gacl.domain.Order">
select order_id id, order_no orderNo, order_price price from orders where order_id=#{id}
</select>
<!-- 3. 使用 resultMap 進行精確映射 -->
<select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
select * from orders where order_id=#{id}
</select>
<resultMap type="me.gacl.domain.Order" id="orderResultMap">
<id property="id" column="order_id"/>
<result property="orderNo" column="order_no"/>
<result property="price" column="order_price"/>
</resultMap>
</mapper>
測試類 Test2 分別呼叫三個查詢方法:
@Test
public void testGetOrderById() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
String statement = "me.gacl.mapping.orderMapper.getOrderById";
Order order = sqlSession.selectOne(statement, 1);
sqlSession.close();
System.out.println(order); // 輸出:null
}
@Test
public void testGetOrderById2() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
String statement = "me.gacl.mapping.orderMapper.selectOrder";
Order order = sqlSession.selectOne(statement, 1);
sqlSession.close();
System.out.println(order); // 輸出:Order [id=1, orderNo=aaaa, price=23.0]
}
@Test
public void testGetOrderById3() {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
String statement = "me.gacl.mapping.orderMapper.selectOrderResultMap";
Order order = sqlSession.selectOne(statement, 1);
sqlSession.close();
System.out.println(order); // 輸出:Order [id=1, orderNo=aaaa, price=23.0]
}
當實體類屬性與資料表欄位名稱不一致時,MyBatis 無法自動映射,會導致查詢結果為 null。解決方案有二:
<resultMap> 明確定義屬性與欄位的對應關係。結構清晰、可維護性強,推薦用於複雜映射場景。實務上建議優先使用 resultMap,特別是欄位較多或涉及關聯查詢時。