Định nghĩa một entity cơ bản trong Hibernate – JPA

Trong JPA – Hibernate, một entity là một Java class tương ứng với một table trong database, mỗi entity object tương ứng với một dòng trong bảng. JPA yêu cầu một entity class phải cung cấp đầy đủ các metadata để ánh xạ giữa entity class và table như tên cột, kiểu dữ liệu, khoá chính, khoá ngoại, etc.

JPA và Hibernate đều cho phép một entity class cung cấp metadata qua 2 cách: annotationxml descriptors. Trong bài viết này chúng ta sẽ sử dụng annotation để cấu hình một entity class vì tính tiện dụng và dễ làm của nó. Ngoài ra một lợi ích to lớn khi dùng annotation là nó cho phép các metadata được đi cùng entity class thay vì một file xml đặt ở một nơi khác.

Cấu hình Entity

Một entity tương ứng với một table dưới database vì thế nó phải chứa đầy đủ các thông tin như tên bảng, khoá chính, khoá ngoại, các cột trong bảng, etc. 

Entity annotation

Mọi entity class đều phải chứa một @Entity annotation, Hibernate sẽ dựa vào thông tin này để ánh xạ xuống một bảng dưới database.  Một entity class phải có tối thiểu no-agrs constructor và một khoá chính.

@Entity
public class Student {
    
    // fields, getters and setters
    
}

Mặc định tên của entity(lưu ý điểm này giúp mình) sẽ trùng với tên của entity class, chúng ta có thể thay đổi thông qua thuộc tính name trong @Entity annotation.

@Entity(name="student")
public class Student {
    
    // fields, getters and setters
    
}

Note: Bên dưới Hibernate sử dụng các entity object để triển khai các tính năng của ORM nên entity class không được khai báo với final.

@Id annotation

Mỗi một entity phải có một khoá chính dùng để định danh, @Id annotation được dùng để các thuộc tính là khoá chính của table. Chúng ta có thể sinh giá trị cho khóa chính tự động bằng cách sử dụng @GeneratedValue với các chiến lược khác nhau. Có 4 chiến lược khác nhau chúng ta có thể chọn là, AUTO, TABLE, SEQUENCE, và IDENTITY.

@Entity(name = "student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

Ở trên mình chọn IDENTITY, tuỳ chọn này sẽ tạo ra một khoá chính số nguyên tăng dần mỗi khi một dòng dữ liệu mới được thêm vào. Chúng ta không cần quan tâm đến giá trị của khoá chính mà database sẽ chịu trách nhiệm sinh ra giá trị này.

@Table annotation

Mặc định tên table dưới database(chú ý giúp mình chỗ này) cũng sẽ giống với Entity class. Trong trường hợp tên table và tên entity không giống nhau, chúng ta có thể sử dụng @Table annotation để chỉ rõ table tương ứng với entity name.

@Entity
@Table(name="STUDENT")
public class Student {
    
    // fields, getters and setters
    
}

Các bạn cần phân biệt giữa @Entity(name = ‘EntityName’)@Table(name = “TableName”) vì mình thấy rất nhiều bạn bị nhầm lẫn, @Entity(name = ‘EntityName’) dùng để chỉ tên của entity được Hibernate quản lý trong khi @Table(name = “TableName”) chỉ đích danh tên của table dưới database. Ví dụ khi chúng ta sử dụng HQL để truy vấn thì chúng ta cần chỉ định EntityName và Hibernate sẽ dựa vào đó để ánh xạ thành TableName tương ứng.

Hibernate: select m from EntityName m => SQL: select m from TableName m

@Column annotation

Giống như @Table annotation, @Column dùng để mô tả các thông tin của một cột trong database bao gồm name, length, nullable, unique.

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
    private String name;
    
    // other fields, getters and setters
}

Như đoạn code trên mô tả cột STUDENT_NAME có độ dài 50, nullable=false nghĩa là cột name không được trống trong database và cuối cùng unique=false tất là cột name có thể dụng giữa các dòng với nhau,

Transient annotation

@Transient dùng để đánh dấu một thuộc tính trong entity class không phải là một cột tương ứng trong database. Ví dụ chúng ta có thuộc tính age được tính bằng công thức năm hiện tại trừ đi năm sinh, do thuộc age không cần lưu trong database.

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false)
    private String name;
    
    @Transient
    private Integer age;
    
    // other fields, getters and setters
}

Enumerated annotation

@Enumerated được dùng với các cột kiểu Enum trong Java.

public enum Gender {
    MALE, 
    FEMALE
}
@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    @Column(name="STUDENT_NAME", length=50, nullable=false, unique=false)
    private String name;
    
    @Transient
    private Integer age;
        
    @Enumerated(EnumType.STRING)
    private Gender gender;
    
    // other fields, getters and setters
}

Testing

Sau khi cấu hình xong mọi thứ thì chúng ta có thể kiểm thử xem có tạo được dữ liệu tương ứng với Student class xuống database không nha.

import entities.Gender;
import entities.Student;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

    public static void main(String[] agrs) {
        EntityManagerFactory emf =
                Persistence.createEntityManagerFactory("entitySetup");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        Student student = new Student("name", Gender.MALE);
        em.persist(student);
        em.getTransaction().commit();
        em.close();
        emf.close();
    }
}

Output

Hibernate: 
    drop table if exists STUDENT
Hibernate: 
    create table STUDENT (
        id bigint not null auto_increment,
        gender varchar(255),
        STUDENT_NAME varchar(50) not null,
        primary key (id)
    )
Hibernate: 
    /* insert entities.Student
        */ insert 
        into
            STUDENT
            (gender, STUDENT_NAME) 
        values
            (?, ?)

Kết quả có thể thấy rằng Hibernate đã sinh một câu lệnh INSERT SQL để thêm dữ liệu xuống database tương ứng.

Tóm lược

Như vậy qua bài viết này chúng ta đã biết cách cấu hình một entity với các thành phần đơn giản. Ở những phần sau chúng ta sẽ tìm hiểu một số các annotation khác dùng để custom và cấu hình entity class trong nhiều trường hợp khác nhau.

Sau cùng, các bạn có thể tham khảo mã nguồn được mình công khai trên github.

Nếu vẫn chưa biết cách cấu hình một project JPA – Hibermate thì bạn có thể tham khảo bài viết sau để thực hành.

Nguồn tham khảo

https://stackoverflow.com/questions/18732646/name-attribute-in-entity-and-table

https://www.baeldung.com/jpa-entities

0 0 votes
Article Rating
Subscribe
Notify of
guest
2 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
2
0
Would love your thoughts, please comment.x
()
x