Mô tả vấn đề
Khi thực thi truy vấn dữ liệu thông qua bộ máy sinh SQL của MyBatis-Plus, người phát triển có thể gặp phải ngoại lệ net.sf.jsqlparser.parser.ParseException. Lỗi này thường xuất hiện khi cấu hình XML Mapper chứa các câu lệnh SQL động với các clause JOIN, đặc biệt là khi sử dụng từ khóa apply làm tên alias (bối cảnh) cho bảng.
Trong quá trình debug, log hiển thị thông báo lỗi chỉ ra rằng hệ thống phân tích cú pháp không nhận diện được token tại vị trí nhất định, cụ thể là gặp token dấu chấm bất ngờ (unexpected token: '.'). Điều này làm gián đoạn quy trình lọc và thực thi truy vấn liên quan đến các plugin như TenantLineInnerInterceptor.
Code mẫu gặp lỗi (Vòng đời cũ)
Dưới đây là ví dụ minh họa cấu trúc XML trước khi sửa đổi, nơi alias apply gây ra sự cố:
<!-- File: UserMapper.xml -->
<select id="getUserData" resultType="com.example.UserDto">
SELECT u.id AS 'userId',
u.username AS 'userName'
FROM users_table u
<!-- Logic JOIN bị lỗi vì alias 'apply' -->
<if test="filterStatus == 'ACTIVE'">
INNER JOIN application_logs appl ON appl.user_id = u.id
</if>
ORDER BY u.create_time DESC
</select>
Hướng xử lý hiệu quả
Biện pháp khắc phục trực tiếp và đơn giản nhất là tránh đặt tên alias trùng hoặc gần giống với các từ khóa nội bộ mà thư viện MyBatis-Plus hay các công cụ phân tích cú pháp SQL đang sử dụng. Thay thế từ khóa apply bằng một danh sách tham chiếu khác rõ ràng hơn, chẳng hạn như applLog hoặc appList.
Code sau khi tối ưu
Cấu hình lại phần JOIN với tên alias an toàn để đảm bảo JSQLParser hoạt động chính xác:
<select id="getUserData" resultType="com.example.UserDto">
SELECT u.id AS 'userId',
u.username AS 'userName'
FROM users_table u
<!-- Đã sửa alias từ 'apply' thành 'appLog' -->
<if test="filterStatus == 'ACTIVE'">
INNER JOIN application_logs appLog ON appLog.user_id = u.id
</if>
ORDER BY u.create_time DESC
</select>
Phân tích nguyên nhân kỹ thuật
Theo theo dõi traceback (stack trace), lỗi được ném ra từ lớp JsqlParserSupport trong package mybatis-plus-extension. Các interceptor của MyBatis-Plus (ví dụ: phân chia tenant, đếm trang tính toán tự động) sử dụng JSQLParser để kiểm tra và biến đổi SQL trước khi gửi xuống Database.
Cụ thể, khi gặp chuỗi lệnh JOIN, parser sẽ quét các từ vựng (tokens). Mặc dù apply không phải là từ khóa cứng (keyword) trong chuẩn SQL thuần túy, nhưng nó có thể xung đột với logic gán ngữ cảnh hoặc hàm ẩn bên trong MyBatis-Plus (đặc biệt là phiên bản Extension Parser Support). Việc parser bị kẹt và gặp token dấu chấm bất ngờ tại dòng JOIN chứng tỏ quy trình chuyển đổi AST (Abstract Syntax Tree) bị đứt gãy do tên alias không được mong đợi.
Lựa chọn tên đại diện cho bảng nên tuân thủ quy tắc đặt tên camelCase hoặc underscore-case rõ ràng, tránh các từ ngắn phổ biến hoặc có ý nghĩa hàm số học/khớp nối trong hệ thống.