Apache Derby Bài 41: Tích hợp Apache Derby với ORM Framework (Hibernate/JPA) để ánh xạ đối tượng
1. Vấn đề của JDBC thuần và sự ra đời của ORM
Xuyên suốt 40 bài học trước, chúng ta đã thao tác với Apache Derby bằng JDBC thuần (Plain JDBC). Bạn phải viết thủ công các chuỗi SQL (SELECT, INSERT), dùng PreparedStatement gán từng tham số, và dùng vòng lặp duyệt qua ResultSet để lấy từng cột gán vào đối tượng Java (Mapping).
Cách tiếp cận này có 3 nhược điểm lớn trong các dự án Backend quy mô doanh nghiệp:
-
Lặp lại mã (Boilerplate Code): Viết đi viết lại các thao tác CRUD (Thêm, Sửa, Xóa, Tìm kiếm) cho hàng chục bảng rất nhàm chán.
-
Khó bảo trì: Nếu tên cột trong CSDL thay đổi, bạn phải tìm và sửa hàng loạt chuỗi SQL rải rác khắp mã nguồn.
-
Thiếu tư duy hướng đối tượng: Cơ sở dữ liệu nghĩ theo "Bảng và Cột", còn Java nghĩ theo "Lớp và Đối tượng" (Object-Relational Impedance Mismatch).
ORM (Object-Relational Mapping), mà tiêu biểu nhất trong Java là tiêu chuẩn JPA (Java Persistence API) và thư viện Hibernate, ra đời để giải quyết triệt để sự bất đồng này. Thay vì viết SQL, bạn chỉ cần thao tác trên các Đối tượng Java, Hibernate sẽ tự động sinh ra câu lệnh SQL chuẩn của Derby và thực thi ngầm qua JDBC.
2. Cấu hình thư viện Maven
Để tích hợp Hibernate vào dự án sử dụng Derby Network Server, bạn cần khai báo các thư viện sau trong pom.xml:
XML
<dependencies>
<!-- Thư viện Client của Apache Derby -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.17.1.0</version>
</dependency>
<!-- Thư viện Hibernate ORM Core -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.4.4.Final</version> <!-- Hoặc phiên bản mới nhất -->
</dependency>
</dependencies>
3. Cấu hình Hibernate (hibernate.cfg.xml)
Hibernate cần biết cách kết nối tới Derby và quan trọng nhất là Dialect (Phương ngữ SQL). Mỗi hệ quản trị CSDL có cú pháp SQL hơi khác nhau (đặc biệt là cách phân trang, sinh ID tự động). Thuộc tính Dialect giúp Hibernate "nói" chuẩn giọng của Apache Derby.
Tạo tệp hibernate.cfg.xml đặt trong thư mục src/main/resources:
XML
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Cấu hình kết nối JDBC tới Derby Network Server -->
<property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<property name="hibernate.connection.url">jdbc:derby://localhost:1527/my_company_db;create=true</property>
<property name="hibernate.connection.username">admin</property>
<property name="hibernate.connection.password">MatKhauSieuKho123</property>
<!-- Phương ngữ SQL của Apache Derby -->
<property name="hibernate.dialect">org.hibernate.dialect.DerbyDialect</property>
<!-- Tự động tạo bảng dựa trên Class Java (Cực kỳ hữu ích khi dev) -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- Hiển thị SQL Hibernate sinh ra trên Console để debug -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- Đăng ký các lớp Thực thể (Entity) -->
<mapping class="com.hieu.derby.entity.NhanVien"/>
</session-factory>
</hibernate-configuration>
(Lưu ý: Bạn hoàn toàn có thể cấu hình Hibernate sử dụng HikariCP mà chúng ta đã học ở Bài 40 để làm Connection Pool bên dưới).
4. Định nghĩa Lớp thực thể (Entity Mapping)
Giờ đây, bạn không cần phải mở DBeaver để gõ CREATE TABLE nữa. Bạn tạo một Class Java (POJO), gắn các Annotation (Chú thích) của JPA, và Hibernate sẽ tự tạo bảng trong Derby.
Để áp dụng cơ chế tự sinh ID (GENERATED ALWAYS AS IDENTITY) đã học ở Bài 29, ta sử dụng chiến lược GenerationType.IDENTITY.
Java
package com.hieu.derby.entity;
import jakarta.persistence.*;
// Đánh dấu đây là một Thực thể ánh xạ xuống bảng 'nhan_vien'
@Entity
@Table(name = "nhan_vien")
public class NhanVien {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // Tương đương IDENTITY của Derby
@Column(name = "id")
private Integer id;
@Column(name = "ho_ten", nullable = false, length = 100)
private String hoTen;
@Column(name = "chuc_vu", length = 50)
private String chucVu;
@Column(name = "luong")
private Double luong;
// Các hàm Khởi tạo (Constructors) bắt buộc phải có hàm rỗng (No-args)
public NhanVien() {}
public NhanVien(String hoTen, String chucVu, Double luong) {
this.hoTen = hoTen;
this.chucVu = chucVu;
this.luong = luong;
}
// Getters và Setters (Bắt buộc)
// ... (Viết getter/setter cho id, hoTen, chucVu, luong)
}
5. Thực thi các thao tác CRUD bằng Hibernate
Logic nghiệp vụ của bạn bây giờ trở nên vô cùng ngắn gọn và thuần hướng đối tượng (Object-Oriented). Quá trình quản lý Transaction (Bài 30) cũng được trừu tượng hóa.
Java
package com.hieu.derby.orm;
import com.hieu.derby.entity.NhanVien;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class DerbyHibernateDemo {
public static void main(String[] args) {
// 1. Khởi tạo SessionFactory từ file cấu hình (Chỉ làm 1 lần lúc bật app)
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
// 2. Mở một phiên làm việc (Session)
try (Session session = factory.openSession()) {
// Bắt đầu giao dịch (Transaction)
Transaction tx = session.beginTransaction();
try {
// Thao tác CREATE (Thêm mới)
NhanVien nv1 = new NhanVien("Nguyễn Văn A", "Backend Developer", 25000000.0);
session.persist(nv1);
System.out.println("=> Đã lưu nhân viên, Derby tự cấp ID: " + nv1.getId());
// Thao tác READ (Tìm kiếm theo ID)
NhanVien timKiem = session.get(NhanVien.class, 1);
if (timKiem != null) {
System.out.println("=> Tìm thấy: " + timKiem.getHoTen());
// Thao tác UPDATE (Chỉ cần set lại giá trị, Hibernate tự tạo UPDATE SQL)
timKiem.setLuong(30000000.0);
}
// Chốt giao dịch (Commit)
tx.commit();
System.out.println("=> Giao dịch thành công!");
} catch (Exception e) {
// Nếu lỗi, tự động Rollback
if (tx != null) tx.rollback();
e.printStackTrace();
}
} finally {
factory.close();
}
}
}
6. Tổng kết
-
ORM Framework (Hibernate) tạo ra một lớp trừu tượng (Abstraction Layer) bọc lấy tầng JDBC của Apache Derby.
-
Lập trình viên tương tác với dữ liệu thông qua các Đối tượng Java thay vì viết chuỗi SQL dễ sinh lỗi.
-
Phương ngữ
DerbyDialectgiúp Hibernate biên dịch mã HQL/JPA Criteria thành các câu lệnh SQL tối ưu nhất dành riêng cho Engine của Derby. -
GenerationType.IDENTITYtương thích hoàn hảo với cơ sở dữ liệu Derby 10.6 trở lên.
Sử dụng Hibernate thuần trong Java SE vẫn còn yêu cầu bạn phải tự quản lý SessionFactory và Transaction qua mã nguồn. Trong thực tế ngành phát triển phần mềm Backend hiện nay, mọi thứ đều được nhúng vào Spring Boot.
Bài tiếp theo sẽ đưa hệ thống của chúng ta chạm đến tiêu chuẩn kiến trúc hiện đại nhất của doanh nghiệp: Apache Derby Bài 42: Tích hợp Apache Derby vào hệ sinh thái Spring Boot (Spring Data JPA).
All Rights Reserved