Hướng Dẫn Cập Nhật Trường JOB_DATA Kiểu BLOB Trong Bảng JOB_DETAILS Bằng Java Với Quartz Scheduler
Trong quá trình sửa một lỗi liên quan đến Quartz Scheduler, tôi đã gặp phải tình huống cần cập nhật trường JOB_DATA kiểu BLOB trong bảng JOB_DETAILS. Dữ liệu trong trường BLOB này được lưu trữ dưới dạng nhị phân của một đối tượng trong Java. Việc tìm kiếm cách trích xuất và cập nhật đối tượng này gặp nhiều khó khăn, nhưng qua đó, tôi đã tự tạo ra đoạn mã Java để thực hiện nhiệm vụ này. Bài viết này nhằm chia sẻ lại kinh nghiệm của tôi với những ai đang gặp phải tình huống tương tự.
Bước 1: Lấy Dữ Liệu Từ Cơ Sở Dữ Liệu
Do không thể viết mã trực tiếp để truy xuất dữ liệu từ cơ sở dữ liệu sản xuất, tôi đã sử dụng một câu truy vấn SQL để lấy dữ liệu và chuyển đổi. Sử dụng MySQL Workbench, tôi thực hiện truy vấn sau:
sql
SELECT JOB_DATA
FROM scheduler_service.QRTZ_JOB_DETAILS;
Kết quả trả về chỉ hiển thị giá trị 'BLOB'. Để giải mã dữ liệu, tôi đã chuyển đổi nó sang dạng hex bằng cách thay đổi câu truy vấn:
sql
SELECT HEX(JOB_DATA)
FROM scheduler_service.QRTZ_JOB_DETAILS;
Với chuỗi hex, đây là bước tiếp theo tôi thực hiện.
Bước 2: Chuyển Đổi Dữ Liệu Từ Hex Về Đối Tượng Trong Java
Từ chuỗi hex đã thu được, tôi tiến hành chuyển đổi lại thành đối tượng Java như sau:
java
var jobData = hexStringToObject(originHex);
"""
public static Object hexStringToObject(String hexString) throws IOException, ClassNotFoundException {
byte[] byteArray = hexStringToByteArray(hexString);
return deserialize(byteArray);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i + 1), 16));
}
return data;
}
private static Object deserialize(byte[] byteArray) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(bais)) {
return ois.readObject();
}
}
"""
Sau khi nhận được đối tượng Java, tôi kiểm tra kiểu của nó:
java
System.out.println("type: " + data.getClass().getName());
Kết quả cho thấy kiểu đối tượng là org.quartz.JobDataMap
. Tôi tiến hành ép kiểu và in ra thông tin:
java
var jobData = (JobDataMap) hexStringToObject(originHex);
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("Job Data Input: | " + objectMapper.writeValueAsString(data));
Kết quả xuất ra là:
{"ITEM_ID":"b222dc19-2dcf-4017-86b0-9cc0786acf42","JOB_TYPE":"JOB_TYPE_DEMO"}
Bước 3: Cập Nhật Dữ Liệu
Tôi cần thay đổi giá trị của ITEM_ID trước khi cập nhật vào cơ sở dữ liệu:
java
data.put("ITEM_ID", uuid);
Tiếp theo, tôi chuyển đổi đối tượng này về lại dạng hex để thực hiện cập nhật vào cơ sở dữ liệu:
java
String hexString = objectToHexString(data);
"""
public static String objectToHexString(Object obj) throws IOException {
byte[] byteArray = serialize(obj);
return bytesToHex(byteArray);
}
private static byte[] serialize(Object obj) throws IOException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(obj);
return baos.toByteArray();
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = String.format("%02X", b);
hexString.append(hex);
}
return hexString.toString();
}
"""
Cuối cùng, tôi thực hiện cập nhật vào bảng trong cơ sở dữ liệu:
sql
UPDATE QRTZ_JOB_DETAILS
SET JOB_DATA = '<hex_string>'
WHERE id = '...';
Và như vậy, nhiệm vụ đã hoàn tất. Cảm ơn mọi người đã đọc bài viết này. Tôi hy vọng rằng bài viết có thể giúp ích cho những ai đang gặp khó khăn trong việc xử lý dữ liệu BLOB với Quartz Scheduler. Tôi rất mong nhận được sự góp ý để cải thiện kỹ năng viết của mình.
source: viblo