Tìm hiểu về annotation @GeneratedValue trong JPA – Phần 2

Bài viết này tiếp theo phần 1 nhé các bạn!

Strategy tiếp theo mà mình muốn đề cập là strategy GenerationType.SEQUENCE

Các bạn khai báo strategy này trong entity Clazz như sau:

Tương tự như strategy GenerationType.TABLE, strategy GenerationType.SEQUENCE hoạt động cũng dựa vào giá trị của property “hibernate.id.new_generator_mappings” trong tập tin cấu hình của JPA là true hay false.

Nếu giá trị của property này là false thì việc generate giá trị cho cột primary key sẽ dựa vào một database sequence của database mà chúng ta đang sử dụng. Nôm na, các bạn có thể hình dung database sequence là đối tượng sẽ nắm giữ thông tin của các cột primary key trong các bảng, khi chúng ta insert mới một record thì sequence này sẽ trả về giá trị của cột primary key cho record đó để chúng ta có thể insert record này. Hiện tại, MySQL không hỗ trợ database sequence nên trong trường hợp này, khi mình chạy ví dụ, mình bị lỗi sau:

Nếu giá trị của property “hibernate.id.new_generator_mappings” là true, Hibernate sẽ sử dụng một table mặc định tên là hibernate_sequence, để ý là sequence không có s nhé các bạn. Mục đích của table này cũng là để lưu giữ thông tin cho việc generate giá trị của cột primary key trong bảng clazz. Cấu trúc của table này như sau:

Lúc này, nếu các bạn chạy lại ví dụ của mình, các bạn sẽ gặp lỗi sau:

Nguyên nhân là vì để sử dụng bảng hibernate_sequence, chúng ta cần insert giá trị ban đầu cho entity Clazz với sequence_name là Clazz và next_val là 1.

Chạy lại ví dụ, các bạn sẽ thấy kết quả như sau:

Tìm hiểu về annotation @GeneratedValue trong JPA

Như các bạn thấy, ở đây mình đã chạy 2 lần và mỗi lần giá trị của cột next_val trong bảng hibernate_sequence lại tăng lên 1 đơn vị. Lúc đầu, khi chưa có record nào thì một record mới sẽ được insert vào bảng hibernate_sequence với giá trị next_val là 2. Giá trị của cột primary key trong bảng clazz cũng tăng lên 1 đơn vị tương ứng.

Chúng ta cũng có thể thay đổi table mặc định của Hibernate cho strategy này bằng cách sử dụng dụng annotation @SequenceGenerator và khai báo nó như sau:

Trong annotation @SequenceGenerator, thuộc tính sequenceName với giá trị là tên của table mà chúng ta muốn sử dụng, cấu trúc của table này cũng tương tự như table mặc định của Hibernate hibernate_sequence:

allocationSize thì tương tự như strategy GenerationType.TABLE trong trường hợp này nha các bạn!

Phần quan trọng cũng là giá trị của thuộc tính name trong annotation @SequenceGenerator sẽ là giá trị của thuộc tính generator trong annotation @GeneratedValue.

Kết quả:

Tìm hiểu về annotation @GeneratedValue trong JPA

Kế tiếp chúng ta sẽ nói về strategy GenerationType.IDENTITY

Đây là strategy thuận lợi và dễ dàng nhất. Các bạn khai báo strategy này trong entity Clazz như sau:

Strategy này được sử dụng để tận dụng việc một số loại database hỗ trợ việc tự generate giá trị cho cột primary key. Ví dụ như trong bài viết này, chúng ta định nghĩa cột primary key id của table clazz với AUTO_INCREMENT. Với định nghĩa này, mỗi khi chúng ta thêm mới một record cho table clazz, MySQL sẽ giúp chúng ta generate giá trị mới cho cột primary key mà chúng ta không cần làm gì cả.

Không cần phải định nghĩa một table khác nên mình rất khuyến khích các bạn sử dụng strategy này nếu database các bạn đang sử dụng hỗ trợ 😀

Strategy cuối cùng và cũng là strategy mặc định của annotation @GeneratedValue đó là GenerationType.AUTO

Vì nó là strategy mặc định nên các bạn không cần khai báo nó một cách tường minh.

Nếu muốn thì các bạn cũng có thể khai báo tường minh như sau:

Thông thường, chúng ta sẽ sử dụng GenerationType.AUTO khi chúng ta cần generate giá trị cho cột primary key mà không cần phải quan tâm đến cách mà giá trị của cột primary key sẽ được generated. Khi đó, JPA có thể lựa chọn bất kỳ một trong 3 strategy mà chúng ta đã discuss ở trên nha các bạn.


Add Comment