MyBatis(前身 iBatis)是基於 Java 的持久層框架,支援自訂 SQL、預存程序與進階映射。它對 JDBC 進行封裝,讓開發者專注於 SQL 本身,無需處理註冊驅動、建立連線、設定參數、解析結果集等繁瑣流程。透過 XML 或註解配置 Statement、執行 SQL,並將結果自動映射為 Java 物件,大幅降低資料庫開發難度。
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version> </dependency>
mybatis-configuration.xml配置資料來源、交易管理器與 Mapper 映射檔載入路徑:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://host:port/db?characterEncoding=utf-8"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mapper/UserDAO.xml"/>
</mappers>
</configuration>
Mapper 為 MyBatis 核心,定義 SQL 與映射關係。慣例命名為 UserDAO.xml、UserMapper.xml 等,置於 mapper 目錄:
<mapper namespace="namespace">
<select id="selectUserById" parameterType="java.lang.Integer" resultType="com.fq.domain.User">
SELECT * FROM user WHERE id = #{id};
</select>
<select id="selectUserByName" parameterType="java.lang.String" resultType="com.fq.domain.User">
SELECT * FROM user WHERE name LIKE '%${value}%';
</select>
</mapper>
public class User {
private Integer id;
private String name;
private String password;
// 建構子、getter/setter、toString 略
}
public interface UserDAO {
User selectUserById(Integer id) throws Exception;
}
public class UserDAOImpl implements UserDAO {
private SqlSessionFactory factory;
public UserDAOImpl(SqlSessionFactory factory) { this.factory = factory; }
@Override
public User selectUserById(Integer id) throws Exception {
SqlSession session = factory.openSession();
User user = session.selectOne("namespace.selectUserById", id);
session.close();
return user;
}
}
SqlSession 方法需硬編碼 Statement ID,維護困難Mapper 檔 namespace 必須與 DAO 介面完整限定名一致;Statement id 對應介面方法名;parameterType/resultType 對應方法參數/回傳類型。
public interface UserDAO {
User selectUserById(Integer id) throws Exception;
}
// Client 端使用
UserDAO dao = session.getMapper(UserDAO.class);
User user = dao.selectUserById(1);
不指定 parameterType,使用 #{0}、#{1} 索引對應:
<update id="updateUserById">
UPDATE user SET name = #{1}, password = #{2} WHERE id = #{0};
</update>
// 介面:void updateUserById(Integer id, String name, String password);
MyBatis 使用 OGNL 解析物件屬性;Map 方式則以 Key 對應 #{key}。
resultMap 處理欄位不一致<resultMap id="userMap" type="com.fq.domain.User">
<id column="user_id" property="id"/>
<result column="user_name" property="name"/>
<result column="user_password" property="password"/>
</resultMap>
<select id="selectUserByName" parameterType="java.lang.String" resultMap="userMap">
SELECT id user_id, name user_name, password user_password FROM user WHERE name = #{name};
</select>
#{} 與 ${} 差異比較| 語法 | 行為 | 防 SQL 注入 | 適用場景 |
|---|---|---|---|
#{} | 預編譯佔位符,自動類型轉換 | 是 | 一般參數傳遞 |
${} | 字串拼接,無類型轉換 | 否 | 動態排序欄位 ORDER BY ${column} |
SqlSession 非執行緒安全,建議定義為區域變數使用。整合 logback 或 log4j 可於除錯時列印 SQL 執行日誌,配置範例:
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency>
Mapper 映射模式消除樣板程式碼、解決硬編碼問題,是 MyBatis 官方推薦的最佳實踐。掌握參數映射、結果映射、動態 SQL 技巧,能顯著提升資料存取層開發效率與維護性。