傳統 MyBatis 開發中,通過字符串指定 SQL 映射(如 "namespace.id")存在顯著缺陷:拼寫錯誤無法編譯期發現、重構困難、IDE 無法提供智能提示。接口式開發模式(Mapper 接口綁定)完美解決了這些問題,實現了類型安全的數據庫操作。
集中聲明所有數據庫操作方法,參數與返回類型明確:
public interface IVisitorOperation {
// 基礎查詢
Visitor basicQuery(int id);
// CRUD 操作
int add(Visitor visitor);
int delete(int id);
int update(Visitor visitor);
Visitor query(int id);
List<Visitor> getList();
// 進階查詢(後續章節擴展)
List<Visitor> getListByPagenate(PagenateArgs args);
List<Visitor> getListChooseWhenDemo(BasicQueryArgs args);
List<Visitor> getListWhereDemo(BasicQueryArgs args);
List<Visitor> getListForeachDemo(List<Integer> ids);
}
關鍵規則:namespace 必須等於接口全限定名,id 必須與接口方法名完全一致,parameterType/resultType 對應方法參數/返回類型。
<mapper namespace="david.mybatis.demo.IVisitorOperation">
<resultMap type="Visitor" id="visitorRs">
<id column="Id" property="id" />
<result column="Name" property="name" />
<result column="Email" property="email" />
<result column="Status" property="status" />
<result column="CreateTime" property="createTime" />
</resultMap>
<sql id="getListSql"> select * from Visitor where status > 0 </sql>
<insert id="add" parameterType="Visitor" useGeneratedKeys="true" keyProperty="Id">
insert into Visitor (Name, Email, Status, CreateTime)
values (#{name}, #{email}, #{status}, #{createTime})
</insert>
<delete id="delete" parameterType="int">
delete from Visitor where status > 0 and id = #{id}
</delete>
<update id="update" parameterType="Visitor">
update Visitor set Name=#{name}, Email=#{email}, Status=#{status}
where id=#{id} and Status > 0
</update>
<select id="query" parameterType="int" resultType="Visitor">
select Id, Name, Email, Status, CreateTime from visitor
where id=#{id} and Status > 0 order by Id
</select>
<select id="basicQuery" parameterType="int" resultType="Visitor">
select * from visitor where id=#{id} and Status > 0 order by Id
</select>
<select id="getList" resultMap="visitorRs">
<include refid="getListSql" />
</select>
</mapper>
public static void testCRUD() {
SqlSession session = MybatisUtils.getSqlSession();
try {
// 關鍵:通過接口類獲取代理實現
IVisitorOperation vOperation = session.getMapper(IVisitorOperation.class);
// 新增
Visitor visitor = new Visitor("Redis", "redis@example.com");
int insertCount = vOperation.add(visitor);
session.commit();
// 查詢
Visitor queried = vOperation.query(visitor.getId());
// 更新
queried.setName("Redis-Updated");
int updateCount = vOperation.update(queried);
session.commit();
// 列表查詢
List<Visitor> list = vOperation.getList();
// 刪除
int deleteCount = vOperation.delete(visitor.getId());
session.commit();
} finally {
MybatisUtils.closeSession(session);
}
}
| 語法 | 處理方式 | 適用場景 | 安全性 |
|---|---|---|---|
#{param} | 參數化預處理 (PreparedStatement) | 業務參數傳遞 | 防 SQL 注入,首選 |
${param} | 直接字符串替換 | 表名、列名、排序字段等不可參數化場景 | 有注入風險,慎用 |
當查詢列名與實體屬性名不一致(如數據庫下劃線命名 vs Java 駝峰命名)、需要關聯映射、或只需部分列時,必須使用 resultMap:
<resultMap type="Visitor" id="visitorRs">
<id column="visitor_id" property="id" /> <!-- 列別名映射 -->
<result column="Name" property="name" />
<result column="Email" property="email" />
<!-- 可選:開啟駝峰自動映射 -->
<!-- <settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings> -->
</resultMap>
<sql> 片段復用提取通用查詢列、表連接、條件片段,通過 <include refid="..."/> 復用,減少重複,便於維護:
<sql id="getListSql"> select * from Visitor where status > 0 </sql>
<select id="getList" resultMap="visitorRs"> <include refid="getListSql" /> </select>
<sql> + <include> 減少冗餘session.commit()finally 塊中關閉 SqlSessionMyBatis 接口式開發是現代持久層開發的標準範式。通過 Mapper 接口與 XML 映射的雙重綁定,實現了 SQL 定義的集中管理、類型安全的參數傳遞、靈活的結果映射。掌握 namespace/id/parameterType/resultType/resultMap 等核心配置要點,配合 #{} 參數化、<sql> 片段復用等最佳實踐,能構建出健壯、可維護的數據訪問層。