MyBatis 將 Java 呼叫對映至 SQL 陳述式,而參數繫結、陳述式執行與結果集存取則由 JDBC 負責。對映器應讓這個邊界清楚可見:SQL 欄位名稱屬於陳述式,Java 屬性名稱屬於 參數對映與結果對映,任何非標準轉換都應由型別處理器在兩者之間執行。
參數與結果邊界 #
簡單參數可以使用 #{id} 佔位符。物件與 Map 參數會公開具名屬性;對於多個對映器
參數,應使用 @Param,使名稱不依賴編譯器中繼資料:
List<Task> findByState(@Param("state") State state,
@Param("limit") int limit);#{...} 會建立 JDBC 參數標記並繫結值。${...} 會在準備 SQL 之前將文字代入 SQL,
因此僅限於允許清單中的識別碼或無法參數化的片段。絕不能將請求資料直接放入
${...} 運算式。
當欄位標籤與 Java 屬性相符時,自動結果對映較為簡潔。名稱不同、巢狀物件需要明確
識別,或聯結可能造成父資料列重複時,應使用 resultMap:
<resultMap id="taskResult" type="com.example.Task">
<id property="id" column="task_id"/>
<result property="name" column="task_name"/>
<result property="state" column="state"
typeHandler="com.example.StateTypeHandler"/>
</resultMap><id> 對映會識別聯結結果中的物件,並協助 MyBatis 合併重複的父資料。它不會宣告
資料庫條件約束;結構描述仍必須強制執行識別性。
產生的索引鍵 #
對於支援產生索引鍵的資料庫與 JDBC 驅動程式,啟用 useGeneratedKeys 並指定可寫入的
Java 屬性。MyBatis 會在插入後呼叫 JDBC 產生索引鍵 API,並將產生的主索引鍵指派給
該屬性。
<insert id="insert"
parameterType="com.example.Task"
useGeneratedKeys="true"
keyProperty="id">
INSERT INTO task (name) VALUES (#{name})
</insert>Task task = new Task();
task.setName("import");
mapper.insert(task);
long id = task.getId();指派只會填入產生索引鍵的屬性,不會重新載入資料庫預設值、觸發器產生的欄位或其他
不相關欄位。請使用後續的 SELECT、資料庫支援時的 RETURNING 子句,或在資料庫
使用序列或驅動程式不支援 getGeneratedKeys 時使用 selectKey 陳述式。
Null 參數 #
UPDATE task
SET completed_at = #{completedAt, jdbcType=TIMESTAMP}
WHERE id = #{id}只有在資料庫慣例與所有可為 null 的參數相容時,才設定全域 jdbcTypeForNull。對於
具有不同 SQL 型別的欄位,針對每個參數指定型別更加清楚。由於產生索引鍵與 null
繫結行為取決於驅動程式,請使用正式環境的驅動程式測試插入與更新。
動態 SQL 與型別處理器 #
動態元素可以建構陳述式結構,而不必串接任意應用程式文字:
<select id="find" resultMap="taskResult">
SELECT id AS task_id, name AS task_name, state
FROM task
<where>
<if test="state != null">
state = #{state, typeHandler=com.example.StateTypeHandler}
</if>
</where>
ORDER BY id
</select>只有在子元素輸出條件時,<where> 才會插入 WHERE,並移除開頭的 AND 或 OR。
相關元素包括 <choose>、<set>、<trim> 與 <foreach>。TypeHandler 應定義
刻意設計的 Java/JDBC 表示方式,例如將列舉儲存為穩定字串;若不同欄位以不同方式
編碼相同的 Java 型別,應進行窄範圍註冊。
工作階段與交易所有權 #
對映的陳述式會透過 SqlSession 執行。直接使用 MyBatis 時,呼叫方會開啟工作階段、
提交或回復交易,並關閉工作階段:
try (SqlSession session = factory.openSession()) {
TaskMapper mapper = session.getMapper(TaskMapper.class);
mapper.insert(task);
session.commit();
}預設工作階段不是自動提交模式,且 SqlSession 不具備執行緒安全性。MyBatis-Spring
等架構整合會將工作階段繫結至架構管理的交易;應用程式程式碼不得將手動提交與該
所有權模型混用。產生索引鍵的指派發生在陳述式執行期間,但只有在擁有該交易的交易
提交後,資料列才會持久化。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)