承接上一篇《JavaWeb 實戰之商城項目開發(一)》完成實體類與分頁對象的建立,本文將深入講解如何利用 MyBatis 搭建資料存取層(DAO),實現資料庫的增刪改查操作。
首先將 MyBatis 核心包與 MySQL 驅動包(mysql-connector-java)放入專案的 lib 目錄,或透過 Maven 管理依賴。
MyBatis 的核心配置文件定義了資料庫連線環境、型別別名、映射器註冊等關鍵資訊。以下是標準配置範例:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="Config.properties"/>
<typeAliases>
<package name="com.model"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<environment id="publish">
<transactionManager type="JDBC"/>
<dataSource type="POOLED"/>
</environment>
</environments>
<mappers>
<mapper resource="com/model/User.xml"/>
</mappers>
</configuration>
resultType 寫法。default 指定預設環境。POOLED 連線池模式,提升資料庫存取效能。以 UserDao 為例,定義 SQL 映射:
<?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="com.model.User">
<select id="load" parameterType="int" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<insert id="add" parameterType="User">
INSERT INTO user VALUES (null, #{username}, #{password}, #{nickname}, #{type})
</insert>
<delete id="delete" parameterType="int">
DELETE FROM user WHERE id = #{id}
</delete>
<update id="update" parameterType="User">
UPDATE user SET username=#{username}, password=#{password}, nickname=#{nickname}, type=#{type} WHERE id=#{id}
</update>
<select id="login" parameterType="String" resultType="User">
SELECT * FROM user WHERE username = #{username}
</select>
<select id="find" parameterType="Map" resultType="User">
SELECT * FROM user
<if test="name != null">
WHERE (username LIKE #{name} OR nickname LIKE #{name})
</if>
ORDER BY ${sort} ${order}
LIMIT #{pageStart}, #{pageSize}
</select>
<select id="findcount" parameterType="Map" resultType="int">
SELECT COUNT(*) FROM user
<if test="name != null">
WHERE (username LIKE #{name} OR nickname LIKE #{name})
</if>
</select>
</mapper>
#{param}:預編譯參數,自動處理類型與防注入,字串會自動加引號。${param}:直接字串替換,適用於 ORDER BY、表名等無法預編譯的場景,需注意 SQL 注入風險。<if>、<where>、<foreach> 等標籤實現動態 SQL 組裝。為簡化 DAO 層程式碼,將 SqlSession 的獲取與關閉封裝為工具類:
package com.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SessionUtil {
private static SqlSessionFactory factory = null;
static {
try {
InputStream is = Resources.getResourceAsStream("Config.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSession() {
return factory.openSession();
}
public static void closeSession(SqlSession session) {
if (session != null) {
session.close();
}
}
}
public interface UserDao {
User load(int id);
boolean add(User user);
boolean delete(int id);
boolean update(User user);
User login(String username, String password);
Pager<User> find(String name, String sort, String order);
}
所有方法遵循統一模式:獲取 Session → 執行操作 → 提交/回滾 → 關閉 Session。以新增用戶為例:
public boolean add(User user) {
SqlSession session = SessionUtil.getSession();
try {
int result = session.insert("com.model.User.add", user);
session.commit();
return result > 0;
} catch (Exception e) {
session.rollback();
e.printStackTrace();
return false;
} finally {
SessionUtil.closeSession(session);
}
}
結合 SystemContext 管理分頁參數,透過 Map 傳遞動態條件:
public Pager<User> find(String name, String sort, String order) {
int pageStart = SystemContext.getPageStart();
int pageSize = SystemContext.getPageSize();
Map<String, Object> params = new HashMap<>();
if (name != null && !name.isEmpty()) {
params.put("name", "%" + name + "%");
}
params.put("sort", sort != null ? sort : "id");
params.put("order", order != null ? order : "asc");
params.put("pageStart", pageStart);
params.put("pageSize", pageSize);
SqlSession session = SessionUtil.getSession();
try {
List<User> data = session.selectList("com.model.User.find", params);
int total = session.selectOne("com.model.User.findcount", params);
Pager<User> pager = new Pager<>();
pager.setDatas(data);
pager.setTotalRecord(total);
pager.setPageSize(pageSize);
pager.setPageStart(pageStart);
return pager;
} finally {
SessionUtil.closeSession(session);
}
}
目前專案已完成實體層、DAO 層及工具類建構。下一步將抽取通用 BaseDao,減少重複程式碼,並深入探討 MyBatis 進階特性(延遲載入、快取、插件機制等)。