Tổng Quan Về Dynamic SQL
Trong quy trình phát triển ứng dụng chuẩn hóa sử dụng JDBC thuần túy, việc xây dựng các câu lệnh truy vấn chứa nhiều điều kiện phức tạp thường gặp khó khăn do phải thực hiện thao niệm chuỗi ký tự thủ công. Quy trình này không chỉ tốn thời gian mà còn tiềm ẩn nguy cơ lỗi cú pháp cao. Giải pháp được đưa ra bởi MyBatis cho phép nhà phát triển định nghĩa các đoạn mã SQL linh hoạt thông qua OGNL (Object Graph Navigation Language), giúp loại bỏ gánh nặng concatenation và đảm bảo tính chính xác khi tạo query.
Công cụ hỗ trợ chính cho tính năng này hoạt động tương tự như JSTL trên nền tảng Java Web nhưng tích hợp sâu hơn vào lớp ORM. Phiên bản MyBatis 3 đã tối ưu hóa bộ sưu tập thẻ, giảm đáng kể số lượng component cần học so với các phiên bản trước nhờ sử dụng biểu thức OGNL mạnh mẽ.
Xử Lý Điều Kiện Đơn Giản - Thẻ
Một trường hợp phổ biến nhất là thêm phần tử điều kiện vào mệnh đề WHERE tùy thuộc vào sự tồn tại của giá trị đầu vào. Ví dụ dưới đây minh họa cách lọc dữ liệu blog khi có tham số tiêu đề hoặc không.
<!-- Ví dụ tìm kiếm danh sách Blog -->
<select id="timSanPhamTheotieuDe" resultType="BlogModel">
SELECT * FROM BLOG_TABLE
WHERE trangThai = 'HOAT_DONG'
<if test="ten != null">
AND tenSanPham LIKE #{ten}
</if>
</select>
Nếu tham số `ten` bị trả về null, hệ thống sẽ chỉ trả về tất cả các bản ghi có trạng thái `HOAT_DONG`. Ngược lại, nếu có nội dung đầu vào, truy vấn sẽ kết hợp thêm điều kiện khớp tên. Đối với các yêu cầu mở rộng hơn như lọc theo tiêu đề hoặc tác giả cùng lúc:
<select id="timSanPhamKetHop" resultType="BlogModel">
SELECT * FROM BLOG_TABLE
WHERE trangThai = 'HOAT_DONG'
<if test="ten != null">
AND tenSanPham LIKE #{ten}
</if>
<if test="tacGia.ten != null">
AND ma_tac_gia LIKE #{tacGia.ten}
</if>
</select>
Chọn Lựa Duy Nhất - Thẻ , ,
Trường hợp bạn không muốn áp dụng tất cả các điều kiện đồng thời mà cần chọn lựa duy nhất một nhánh xử lý dựa trên tiêu chí ưu tiên, MyBatis cung cấp cấu trúc tương tự câu lệnh switch-case.
Xét ví dụ sau: Ưu tiên tìm kiếm theo tên nếu có, tiếp theo là tác giả nếu không có tên, cuối cùng là danh sách gợi ý (featured) nếu không có thông tin lọc nào.
<select id="timSanPhamTheoUuTien" resultType="BlogModel">
SELECT * FROM BLOG_TABLE
WHERE trangThai = 'HOAT_DONG'
<choose>
<when test="ten != null">
AND tenSanPham LIKE #{ten}
</when>
<when test="tacGia.ten != null">
AND ma_tac_gia LIKE #{tacGia.ten}
</when>
<otherwise>
AND sanPhamNoiBat = 1
</otherwise>
</choose>
</select>
Bổ Sung Tự Động Mệnh Đề Where Và Set
Một vấn đề kinh điển khi dùng thẻ `
MyBatis giải quyết vấn đề này bằng thẻ `
<select id="timTheoNhieuDieuKien" resultType="BlogModel">
SELECT * FROM BLOG_TABLE
<where>
<if test="trangThai != null">
trangThai = #{trangThai}
</if>
<if test="ten != null">
AND tenSanPham LIKE #{ten}
</if>
<if test="tacGia.ten != null">
AND ma_tac_gia LIKE #{tacGia.ten}
</if>
</where>
</select>
Về nguyên tắc, thẻ này thực chất là wrapper của thẻ `
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
Tương tự, đối với câu lệnh cập nhật dữ liệu, thẻ `
<update id="capNhatThongTinTaiKhoan">
UPDATE USER_INFO
<set>
<if test="username != null">ten_dang_nhap=#{username},</if>
<if test="password != null">mat_khau=#{password},</if>
<if test="email != null">dia_chi_email=#{email},</if>
<if test="bio != null">tieu_su=#{bio}</if>
</set>
WHERE ma_user = #{id}
</update>
Kết quả của thẻ set cũng có thể được mô phỏng bằng trim override hậu tố:
<trim prefix="SET" suffixOverrides=", ">
...
</trim>
Lặp Duyệt Bộ Sưu Tập - Thẻ
Khi cần kiểm tra xem một giá trị có thuộc tập hợp nào đó không (kiểu điều kiện IN list), thẻ `
<select id="layDanhSachDonHang" resultType="OrderModel">
SELECT * FROM ORDER_T
WHERE ma_don_hang IN
<foreach item="mavalue" collection="list"
open="(" separator="," close=")">
#{mavalue}
</foreach>
</select>
Thuộc tính quan trọng bao gồm `collection` (danh sách đầu vào), `item` (biến đại diện từng phần tử), `separator` (ngăn cách giữa các giá trị), và `open/close` (vòng kẹp đầu/cuối). Thẻ này hiểu rõ việc thêm dấu ngăn cách để tránh lỗi cú pháp cuối mảng. Nó hỗ trợ bất kỳ object nào implements Iterable như List, Set, Map hoặc Array.
Sử Dụng Trong Mapper Theo Java Annotation
Khi làm việc trực tiếp với file interface Java thay vì XML mapping, ta có thể nhúng logic động ngay trong注解 Update hoặc Select thông qua thẻ `