Hibernate
Trang này chứa các mẹo và tài nguyên để chuẩn bị cho buổi phỏng vấn Hibernate.
ORM trong Hibernate là gì? Hibernate ORM là viết tắt của Object Relational Mapping (Ánh xạ Quan hệ Đối tượng). Đây là một mẫu công cụ ánh xạ chủ yếu được sử dụng để chuyển đổi dữ liệu được lưu trữ trong cơ sở dữ liệu quan hệ thành các đối tượng được sử dụng trong các cấu trúc lập trình hướng đối tượng. Công cụ này cũng hỗ trợ rất nhiều trong việc đơn giản hóa việc truy xuất, tạo và thao tác dữ liệu.
Ưu điểm của Hibernate so với JDBC là gì?
Mã sạch và dễ đọc: Sử dụng Hibernate giúp loại bỏ nhiều mã mẫu (boiler-plate code) dựa trên API JDBC, từ đó làm cho mã nguồn trông sạch hơn và dễ đọc hơn.
HQL (Hibernate Query Language): Hibernate cung cấp HQL, một ngôn ngữ gần với Java và mang tính hướng đối tượng. Điều này giúp giảm gánh nặng cho lập trình viên trong việc viết các truy vấn độc lập với cơ sở dữ liệu. Trong JDBC, điều này không khả thi, lập trình viên cần biết các mã đặc thù của từng cơ sở dữ liệu.
Quản lý giao dịch: JDBC không hỗ trợ quản lý giao dịch ngầm. Lập trình viên phải tự viết mã quản lý giao dịch bằng các phương thức commit và rollback. Trong khi đó, Hibernate cung cấp tính năng này một cách ngầm định.
Xử lý ngoại lệ: Hibernate bao bọc các ngoại lệ JDBC và ném ra các ngoại lệ không kiểm tra như JDBCException hoặc HibernateException. Điều này, cùng với hệ thống quản lý giao dịch tích hợp, giúp lập trình viên tránh phải viết nhiều khối try-catch để xử lý ngoại lệ. Trong JDBC, ngoại lệ SQLException là ngoại lệ được kiểm tra, buộc lập trình viên phải viết khối try-catch tại thời điểm biên dịch.
Tính năng đặc biệt: Hibernate hỗ trợ các tính năng OOP như kế thừa, liên kết và cũng hỗ trợ các tập hợp (collections). Những tính năng này không có trong JDBC.
Một số giao diện quan trọng của framework Hibernate là gì? Các giao diện cốt lõi của Hibernate bao gồm:
Configuration
SessionFactory
Session
Criteria
Query
Transaction
Session trong Hibernate là gì? Session là một đối tượng duy trì kết nối giữa ứng dụng Java và cơ sở dữ liệu. Session cũng cung cấp các phương thức để lưu trữ, truy xuất, sửa đổi hoặc xóa dữ liệu khỏi cơ sở dữ liệu bằng các phương thức như persist(), load(), get(), update(), delete(), v.v. Ngoài ra, nó có các phương thức factory để trả về các đối tượng Query, Criteria và Transaction.
SessionFactory là gì? SessionFactory cung cấp một thể hiện của Session. Đây là một lớp factory tạo ra các đối tượng Session dựa trên các tham số cấu hình để thiết lập kết nối với cơ sở dữ liệu. Theo thông lệ tốt, ứng dụng thường chỉ có một thể hiện duy nhất của SessionFactory. Trạng thái bên trong của SessionFactory, bao gồm siêu dữ liệu về ORM, là bất biến, tức là một khi thể hiện được tạo, nó không thể thay đổi. Nó cũng cung cấp khả năng lấy thông tin như thống kê và siêu dữ liệu liên quan đến một lớp, các lần thực thi truy vấn, v.v. Ngoài ra, nó lưu trữ dữ liệu bộ nhớ đệm cấp hai (second-level cache) nếu được kích hoạt.
Bạn có thể giải thích khái niệm tải lười (lazy loading) trong Hibernate không? Tải lười (lazy loading) chủ yếu được sử dụng để cải thiện hiệu suất ứng dụng bằng cách giúp tải các đối tượng con theo nhu cầu. Cần lưu ý rằng, kể từ phiên bản Hibernate 3, tính năng này đã được bật mặc định. Điều này có nghĩa là các đối tượng con không được tải cho đến khi đối tượng cha được tải.
Sự khác biệt giữa bộ nhớ đệm cấp một và bộ nhớ đệm cấp hai là gì? Hibernate có 2 loại bộ nhớ đệm: bộ nhớ đệm cấp một (first-level cache) và bộ nhớ đệm cấp hai (second-level cache), với sự khác biệt như sau:
Bộ nhớ đệm cấp một
Bộ nhớ đệm cấp hai
Chỉ tồn tại cục bộ trong đối tượng Session và không thể chia sẻ giữa nhiều Session.
Được duy trì ở cấp SessionFactory và chia sẻ giữa tất cả các Session trong Hibernate.
Được bật mặc định và không thể tắt.
Tắt mặc định, nhưng có thể bật thông qua cấu hình.
Chỉ tồn tại cho đến khi Session còn mở, khi Session đóng, bộ nhớ đệm cấp một bị hủy.
Tồn tại trong suốt vòng đời của ứng dụng, chỉ bị hủy và tạo lại khi ứng dụng khởi động lại.
Nếu một thực thể hoặc đối tượng được tải bằng phương thức get(), Hibernate sẽ kiểm tra bộ nhớ đệm cấp một trước. Nếu không tìm thấy, nó sẽ kiểm tra bộ nhớ đệm cấp hai nếu được cấu hình. Nếu vẫn không tìm thấy, nó sẽ truy vấn cơ sở dữ liệu và trả về đối tượng, hoặc trả về null nếu không có hàng tương ứng trong bảng.
Bạn có thể giải thích khái niệm ánh xạ kế thừa (Inheritance Mapping) trong Hibernate không? Java là một ngôn ngữ lập trình hướng đối tượng, và kế thừa là một trong những trụ cột quan trọng nhất của nguyên tắc hướng đối tượng. Để biểu diễn bất kỳ mô hình nào trong Java, kế thừa thường được sử dụng để đơn giản hóa mối quan hệ. Tuy nhiên, có một vấn đề: cơ sở dữ liệu quan hệ không hỗ trợ kế thừa. Chúng có cấu trúc phẳng. Có các chiến lược ánh xạ kế thừa khác nhau:
Single Table Strategy (Chiến lược bảng đơn)
Table Per Class Strategy (Chiến lược mỗi lớp một bảng)
Mapped Super Class Strategy (Chiến lược lớp cha được ánh xạ)
Joined Table Strategy (Chiến lược bảng kết hợp)
Các chú thích (annotation) phổ biến nhất được sử dụng để hỗ trợ ánh xạ Hibernate là gì?
javax.persistence.Entity: Chú thích này được sử dụng trên các lớp mô hình bằng “@Entity” và cho biết rằng các lớp đó là các bean thực thể.
javax.persistence.Table: Chú thích này được sử dụng trên các lớp mô hình bằng “@Table” và cho biết lớp ánh xạ với tên bảng trong cơ sở dữ liệu.
javax.persistence.Access: Được sử dụng dưới dạng “@Access” để định nghĩa loại truy cập là field hoặc property. Nếu không chỉ định, giá trị mặc định là “field”.
javax.persistence.Id: Được sử dụng dưới dạng “@Id” trên một thuộc tính trong lớp để chỉ ra rằng thuộc tính đó là khóa chính của bean thực thể.
javax.persistence.EmbeddedId: Được sử dụng dưới dạng “@EmbeddedId” trên thuộc tính và chỉ ra rằng đó là khóa chính tổng hợp của bean thực thể.
javax.persistence.Column: “@Column” được sử dụng để định nghĩa tên cột trong bảng cơ sở dữ liệu.
javax.persistence.GeneratedValue: “@GeneratedValue” được sử dụng để định nghĩa chiến lược tạo khóa chính, kết hợp với enum javax.persistence.GenerationType.
javax.persistence.OneToOne: “@OneToOne” được sử dụng để định nghĩa ánh xạ một-một giữa hai bean thực thể. Tương tự, Hibernate cung cấp OneToMany, ManyToOne và ManyToMany cho các loại ánh xạ khác nhau.
org.hibernate.annotations.Cascade: Chú thích “@Cascade” được sử dụng để định nghĩa hành động phân cấp giữa hai bean thực thể, kết hợp với enum org.hibernate.annotations.CascadeType để xác định loại phân cấp.
Phân biệt giữa get() và load() trong phiên Hibernate
get()
load()
Lấy dữ liệu từ cơ sở dữ liệu ngay khi được gọi.
Trả về một đối tượng proxy và chỉ tải dữ liệu khi cần thiết.
Cơ sở dữ liệu được truy vấn mỗi lần phương thức được gọi.
Cơ sở dữ liệu chỉ được truy vấn khi thực sự cần, gọi là Lazy Loading, giúp phương thức hiệu quả hơn.
Trả về null nếu không tìm thấy đối tượng.
Ném ngoại lệ ObjectNotFoundException nếu không tìm thấy đối tượng.
Nên dùng khi không chắc chắn về sự tồn tại của dữ liệu trong cơ sở dữ liệu.
Nên dùng khi chắc chắn rằng dữ liệu tồn tại trong cơ sở dữ liệu.
API Criteria trong Hibernate là gì? API Criteria trong Hibernate giúp lập trình viên xây dựng các truy vấn tiêu chí động trên cơ sở dữ liệu bền vững. API Criteria là một lựa chọn mạnh mẽ và linh hoạt hơn so với các truy vấn HQL (Hibernate Query Language) để tạo các truy vấn động. API này cho phép phát triển các đối tượng truy vấn tiêu chí theo cách lập trình. Giao diện org.hibernate.Criteria được sử dụng cho mục đích này. Giao diện Session của framework Hibernate có phương thức createCriteria() nhận lớp của đối tượng bền vững hoặc tên thực thể làm tham số và trả về thể hiện đối tượng bền vững mà truy vấn tiêu chí được thực thi. Nó cũng giúp dễ dàng áp dụng các hạn chế để truy xuất dữ liệu có chọn lọc từ cơ sở dữ liệu, thông qua phương thức add() nhận đối tượng org.hibernate.criterion.Criterion đại diện cho từng hạn chế riêng lẻ.
HQL là gì? Hibernate Query Language (HQL) là một phần mở rộng của SQL. Nó đơn giản, hiệu quả và rất linh hoạt để thực hiện các thao tác phức tạp trên cơ sở dữ liệu quan hệ mà không cần viết các truy vấn phức tạp. HQL là biểu diễn hướng đối tượng của ngôn ngữ truy vấn, tức là thay vì sử dụng tên bảng, chúng ta sử dụng tên lớp, điều này làm cho ngôn ngữ này độc lập với bất kỳ cơ sở dữ liệu nào.
Hibernate có hỗ trợ truy vấn SQL gốc không? Có, Hibernate hỗ trợ. Hibernate cung cấp phương thức createSQLQuery() để cho phép lập trình viên gọi trực tiếp câu lệnh SQL gốc và trả về một đối tượng Query.
Vấn đề N+1 SELECT trong Hibernate là gì? Vấn đề N+1 SELECT xuất hiện do kết quả của việc sử dụng chiến lược tải lười (lazy loading) và lấy theo nhu cầu. Ví dụ, nếu bạn có một danh sách N mục và mỗi mục trong danh sách có phụ thuộc vào một tập hợp của đối tượng khác (giả sử là bid), để tìm bid cao nhất cho mỗi mục khi sử dụng chiến lược tải lười, Hibernate phải thực hiện 1 truy vấn để tải tất cả các mục, sau đó thực hiện thêm N truy vấn để tải bid của từng mục. Do đó, Hibernate thực sự thực thi N+1 truy vấn.
Làm thế nào để giải quyết vấn đề N+1 SELECT trong Hibernate? Một số chiến lược để giải quyết vấn đề N+1 SELECT bao gồm:
Tải trước các bản ghi theo lô, giúp giảm vấn đề từ N+1 xuống (N/K) + 1, trong đó K là kích thước của lô.
Sử dụng chiến lược lấy subselect.
Như một giải pháp cuối cùng, cố gắng tránh hoặc tắt hoàn toàn tải lười.
Chiến lược Single Table là gì? Single Table Strategy là một chiến lược của Hibernate để thực hiện ánh xạ kế thừa. Chiến lược này được coi là tốt nhất trong số các chiến lược hiện có. Ở đây, hệ thống phân cấp dữ liệu kế thừa được lưu trữ trong một bảng duy nhất bằng cách sử dụng một cột phân biệt (discriminator column) để xác định bản ghi thuộc về lớp nào.
Chiến lược Table Per Class là gì? Table Per Class Strategy là một loại chiến lược ánh xạ kế thừa khác, trong đó mỗi lớp trong hệ thống phân cấp có một bảng cơ sở dữ liệu ánh xạ tương ứng. Hibernate cung cấp chú thích @Inheritance nhận strategy làm tham số để định nghĩa chiến lược nào sẽ được sử dụng. Bằng cách gán giá trị InheritanceType.TABLE_PER_CLASS, điều này cho biết chúng ta đang sử dụng chiến lược mỗi lớp một bảng để ánh xạ.
Truy vấn SQL có tên (Named SQL Query) là gì? Named SQL Query là một biểu thức được biểu diễn dưới dạng bảng. Ở đây, các biểu thức SQL để chọn/lấy các hàng và cột từ một hoặc nhiều bảng trong một hoặc nhiều cơ sở dữ liệu có thể được chỉ định. Điều này giống như sử dụng bí danh cho các truy vấn. Trong Hibernate, chúng ta có thể sử dụng các chú thích @NamedQueries và @NamedQuery.
Last updated