JPA ( Chú thích về tính bền của Java ) là giải pháp tiêu chuẩn của Java để thu hẹp khoảng cách giữa các mô hình miền hướng đối tượng và hệ thống cơ sở dữ liệu quan hệ. Ý tưởng là ánh xạ các lớp Java tới các bảng quan hệ và thuộc tính của các lớp đó với các hàng trong bảng. Điều này thay đổi ngữ nghĩa của trải nghiệm tổng thể về mã hóa Java bằng cách hợp tác liền mạch hai công nghệ khác nhau trong cùng một mô hình lập trình. Bài viết này cung cấp một cái nhìn tổng quan và việc triển khai hỗ trợ của nó trong Java.
Tổng quan
Cơ sở dữ liệu quan hệ có lẽ là ổn định nhất trong số tất cả các công nghệ bền bỉ có sẵn trong máy tính thay vì tất cả những phức tạp liên quan đến nó. Đó là bởi vì ngày nay, ngay cả trong thời đại được gọi là “dữ liệu lớn”, cơ sở dữ liệu quan hệ “NoSQL” vẫn luôn có nhu cầu và đang phát triển mạnh. Cơ sở dữ liệu quan hệ là công nghệ ổn định không chỉ bằng lời nói mà bởi sự tồn tại của nó qua nhiều năm. NoSQL có thể tốt để xử lý số lượng lớn dữ liệu có cấu trúc trong doanh nghiệp, nhưng rất nhiều khối lượng công việc giao dịch được xử lý tốt hơn thông qua cơ sở dữ liệu quan hệ. Ngoài ra, có một số công cụ phân tích tuyệt vời được liên kết với cơ sở dữ liệu quan hệ.
Để giao tiếp với cơ sở dữ liệu quan hệ, ANSI đã chuẩn hóa một ngôn ngữ gọi là SQL ( Ngôn ngữ truy vấn có cấu trúc ). Một câu lệnh được viết bằng ngôn ngữ này có thể được sử dụng cho cả việc xác định và thao tác dữ liệu. Tuy nhiên, vấn đề của SQL trong xử lý Java là chúng có cấu trúc cú pháp không khớp và rất khác nhau về cốt lõi, nghĩa là, SQL là thủ tục trong khi Java là hướng đối tượng. Vì vậy, một giải pháp làm việc được tìm kiếm sao cho Java có thể nói theo hướng đối tượng và cơ sở dữ liệu quan hệ vẫn có thể hiểu nhau. JPA là câu trả lời cho cuộc gọi đó và cung cấp cơ chế để thiết lập giải pháp làm việc giữa hai bên.
Liên quan đến Ánh xạ đối tượng
Các chương trình Java tương tác với cơ sở dữ liệu quan hệ bằng cách sử dụng JDBC ( Khả năng kết nối cơ sở dữ liệu Java ) API. Trình điều khiển JDBC là chìa khóa cho kết nối và cho phép chương trình Java thao tác với cơ sở dữ liệu đó bằng cách sử dụng API JDBC. Khi kết nối được thiết lập, chương trình Java kích hoạt các truy vấn SQL ở dạng Chuỗi s để giao tiếp các thao tác tạo, chèn, cập nhật và xóa. Điều này là đủ cho tất cả các mục đích thực tế, nhưng không thuận tiện theo quan điểm của lập trình viên Java. Điều gì sẽ xảy ra nếu cấu trúc của bảng quan hệ có thể được tạo lại thành các lớp Java thuần túy và sau đó bạn có thể xử lý chúng theo cách hướng đối tượng thông thường? Cấu trúc của một bảng quan hệ là một biểu diễn lôgic của dữ liệu dưới dạng bảng. Các bảng bao gồm các cột mô tả các thuộc tính thực thể và các hàng là tập hợp các thực thể. Ví dụ:bảng EMPLOYEE có thể chứa các thực thể sau với các thuộc tính của chúng.
Emp_number | Tên | dept_no | Mức lương | Địa điểm |
112233 | Peter | 123 | 1200 | LA |
112244 | Ray | 234 | 1300 | NY |
112255 | Sandip | 123 | 1400 | NJ |
112266 | Kalpana | 234 | 1100 | LA |
Các hàng là duy nhất theo khóa chính (emp_number) trong một bảng; điều này cho phép tìm kiếm nhanh chóng. Một bảng có thể liên quan đến một hoặc nhiều bảng bằng một số khóa, chẳng hạn như khóa ngoại (dept_no), liên quan đến hàng tương đương trong bảng khác.
Theo đặc tả Java Persistence 2.1, JPA bổ sung hỗ trợ tạo lược đồ, các phương pháp chuyển đổi kiểu, sử dụng biểu đồ thực thể trong các truy vấn và hoạt động tìm, ngữ cảnh liên tục không đồng bộ hóa, gọi thủ tục được lưu trữ và đưa vào các lớp trình nghe thực thể. Nó cũng bao gồm các cải tiến đối với ngôn ngữ truy vấn Java Persistence, API tiêu chí và ánh xạ các truy vấn gốc.
Nói tóm lại, nó làm mọi thứ để tạo ra ảo tưởng rằng không có phần thủ tục nào trong việc xử lý cơ sở dữ liệu quan hệ và mọi thứ đều hướng đối tượng.
Triển khai JPA
JPA mô tả quản lý dữ liệu quan hệ trong ứng dụng Java. Nó là một đặc điểm kỹ thuật và có một số cách triển khai của nó. Một số triển khai phổ biến là Hibernate, EclipseLink và Apache OpenJPA. JPA định nghĩa siêu dữ liệu thông qua các chú thích trong các lớp Java hoặc qua các tệp cấu hình XML. Tuy nhiên, chúng ta có thể sử dụng cả XML và chú thích để mô tả siêu dữ liệu. Trong trường hợp như vậy, cấu hình XML sẽ ghi đè các chú thích. Điều này là hợp lý vì các chú thích được viết bằng mã Java, trong khi các tệp cấu hình XML nằm ngoài mã Java. Do đó, sau này, nếu có, cần thực hiện các thay đổi trong siêu dữ liệu; trong trường hợp cấu hình dựa trên chú thích, nó yêu cầu quyền truy cập mã Java trực tiếp. Điều này luôn có thể không thực hiện được. Trong trường hợp như vậy, chúng ta có thể viết cấu hình siêu dữ liệu mới hoặc đã thay đổi trong tệp XML mà không có bất kỳ dấu hiệu thay đổi nào trong mã gốc và vẫn có hiệu quả mong muốn. Đây là lợi thế của việc sử dụng cấu hình XML. Tuy nhiên, cấu hình dựa trên chú thích thuận tiện hơn để sử dụng và là lựa chọn phổ biến của các lập trình viên.
- Ngủ đông là phổ biến và tiên tiến nhất trong số tất cả các triển khai JPA do Red Hat. Nó sử dụng các tinh chỉnh riêng và các tính năng bổ sung có thể được sử dụng ngoài việc triển khai JPA. Nó có một cộng đồng người dùng lớn hơn và được ghi lại đầy đủ. Một số tính năng độc quyền bổ sung là hỗ trợ cho việc thuê nhiều người, tham gia các thực thể không liên kết trong các truy vấn, quản lý dấu thời gian, v.v.
- Liên kết Eclipse dựa trên TopLink và là một triển khai tham chiếu của các phiên bản JPA. Nó cung cấp các chức năng JPA tiêu chuẩn ngoài một số tính năng độc quyền thú vị, chẳng hạn như hỗ trợ cho thuê nhiều người, xử lý các sự kiện thay đổi cơ sở dữ liệu, v.v.
Sử dụng JPA trong Chương trình Java SE
Để sử dụng JPA trong chương trình Java, bạn cần một nhà cung cấp JPA như Hibernate hoặc EclipseLink hoặc bất kỳ thư viện nào khác. Ngoài ra, bạn cần một trình điều khiển JDBC kết nối với cơ sở dữ liệu quan hệ cụ thể. Ví dụ, trong đoạn mã sau, chúng tôi đã sử dụng các thư viện sau:
- Nhà cung cấp: EclipseLink
- Trình điều khiển JDBC: Trình điều khiển JDBC cho MySQL (Trình kết nối / J)
Chúng tôi sẽ thiết lập mối quan hệ giữa hai bảng — Nhân viên và Phòng ban — là một đối một và một-nhiều, như được mô tả trong biểu đồ EER sau (xem Hình 1).
Hình 1: Mối quan hệ bảng
Các nhân viên bảng được ánh xạ tới một lớp thực thể bằng cách sử dụng chú thích như sau:
package org.mano.jpademoapp; import javax.persistence.*; @Entity @Table(name = "employee") public class Employee { @Id private int id; private String name; private String phone; private String email; @OneToOne private Department department; public Employee() { super(); } public Employee(int id, String name, String phone, String email) { super(); this.id = id; this.name = name; this.phone = phone; this.email = email; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
Và, bộ phận bảng được ánh xạ tới một lớp thực thể như sau:
package org.mano.jpademoapp; import java.util.*; import javax.persistence.*; @Entity @Table(name = "department") public class Department { @Id private int id; private String location; @OneToMany private List<Employee> employees = new ArrayList<>(); public Department() { super(); } public Department(int id, String location) { super(); this.id = id; this.location = location; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } }
Tệp cấu hình, Persence.xml , được tạo trong META-INF danh mục. Tệp này chứa cấu hình kết nối, chẳng hạn như trình điều khiển JDBC được sử dụng, tên người dùng và mật khẩu để truy cập cơ sở dữ liệu và thông tin liên quan khác mà nhà cung cấp JPA yêu cầu để thiết lập kết nối cơ sở dữ liệu.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi_schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="JPADemoProject" transaction-type="RESOURCE_LOCAL"> <class>org.mano.jpademoapp.Employee</class> <class>org.mano.jpademoapp.Department</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/testdb" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="secret" /> <property name="javax.persistence.schema-generation .database.action" value="drop-and-create"/> <property name="javax.persistence.schema-generation .scripts.action" value="drop-and-create"/> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence>
Các thực thể không tự tồn tại. Logic phải được áp dụng để thao túng các thực thể nhằm quản lý vòng đời liên tục của chúng. EntityManager giao diện do JPA cung cấp cho phép ứng dụng quản lý và tìm kiếm các thực thể trong cơ sở dữ liệu quan hệ. Chúng tôi tạo đối tượng truy vấn với sự trợ giúp của EntityManager để giao tiếp với cơ sở dữ liệu. Để tải xuống EntityManager đối với một cơ sở dữ liệu nhất định, chúng tôi sẽ sử dụng một đối tượng triển khai EntityManagerFactory giao diện. Có một tĩnh phương thức, được gọi là createEntityManagerFactory , trong Persistence lớp trả về EntityManagerFactory cho đơn vị độ bền được chỉ định là Chuỗi lý lẽ. Trong cách triển khai thô sơ sau đây, chúng tôi đã triển khai logic.
package org.mano.jpademoapp; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public enum PersistenceManager { INSTANCE; private EntityManagerFactory emf; private PersistenceManager() { emf=Persistence.createEntityManagerFactory("JPADemoProject"); } public EntityManager getEntityManager() { return emf.createEntityManager(); } public void close() { emf.close(); } }
Bây giờ, chúng ta đã sẵn sàng để tạo giao diện chính của ứng dụng. Ở đây, chúng tôi chỉ triển khai thao tác chèn vì mục đích đơn giản và hạn chế về không gian.
package org.mano.jpademoapp; import javax.persistence.EntityManager; public class Main { public static void main(String[] args) { Department d1=new Department(11, "NY"); Department d2=new Department(22, "LA"); Employee e1=new Employee(111, "Peter", "9876543210", "[email protected]"); Employee e2=new Employee(222, "Ronin", "993875630", "[email protected]"); Employee e3=new Employee(333, "Kalpana", "9876927410", "[email protected]"); Employee e4=new Employee(444, "Marc", "989374510", "[email protected]"); Employee e5=new Employee(555, "Anik", "987738750", "[email protected]"); d1.getEmployees().add(e1); d1.getEmployees().add(e3); d1.getEmployees().add(e4); d2.getEmployees().add(e2); d2.getEmployees().add(e5); EntityManager em=PersistenceManager .INSTANCE.getEntityManager(); em.getTransaction().begin(); em.persist(e1); em.persist(e2); em.persist(e3); em.persist(e4); em.persist(e5); em.persist(d1); em.persist(d2); em.getTransaction().commit(); em.close(); PersistenceManager.INSTANCE.close(); } }
Lưu ý: Vui lòng tham khảo tài liệu Java API thích hợp để biết thông tin chi tiết về các API được sử dụng trong mã trước. |
Kết luận
Như nên hiển nhiên, thuật ngữ cốt lõi của ngữ cảnh JPA và Persistence nhanh hơn so với cái nhìn thoáng qua ở đây, nhưng bắt đầu bằng một cái nhìn tổng quan nhanh sẽ tốt hơn so với mã bẩn phức tạp dài và các chi tiết khái niệm của chúng. Nếu bạn có một chút kinh nghiệm lập trình trong JDBC cốt lõi, chắc chắn bạn sẽ đánh giá cao cách JPA có thể làm cho cuộc sống của bạn đơn giản hơn. Chúng tôi sẽ dần dần tìm hiểu sâu hơn về JPA khi chúng tôi xem xét các bài viết sắp tới.