Các annotation trong JPA được sử dụng để ánh xạ các đối tượng Java sang các bảng, cột trong cơ sở dữ liệu, v.v. Hibernate là một trong những ứng dụng phổ biến nhất của đặc tả JPA và cung cấp thêm một số annotations. Hôm nay chúng ta sẽ tìm hiểu về JPA Annotations và Hibernate Annotations kèm theo một vài đoạn code minh họa ngắn.

JPA Annotations và Hibernate Annotations
Java annotation là một dạng siêu dữ liệu được thêm vào mã nguồn Java. Java annotations có thể được đọc từ các tệp nguồn. Nó cũng có thể được nhúng vào và đọc từ các tệp class do trình biên dịch tạo ra. Điều này cho phép các annotations được giữ lại bởi JVM trong suốt quá trình chạy. JPA annotations không phải là một phần của JDK tiêu chuẩn, vì vậy bạn sẽ nhận được nó khi bạn thêm bất kỳ framework ứng dụng nào. Ví dụ: sự phụ thuộc maven của hibernate dưới đây cũng sẽ cung cấp cho bạn JPA annotations.
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
JPA Annotations để ánh xạ java object tới database table
Hãy cùng xem một vài JPA annotations quan trọng. Lưu ý rằng các annotations này có trong gói javax.persistence.
javax.persistence.Entity: Chỉ định rằng một class là một entity. Annotation này có thể được áp dụng trên Class, Interface hoặc Enums.
import javax.persistence.Entity;
@Entity
public class Employee implements Serializable {
}
@Table: Chỉ định table trong database mà entity này được ánh xạ tới. Trong ví dụ bên dưới, dữ liệu sẽ được lưu trữ trong table “employee”. Thuộc tínhnamecủa annotation@Tableđược dùng để chỉ định tên table.
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
}
@Column: Chỉ định ánh xạ column bằng cách sử dụng annotation@Column. Thuộc tínhnamecủa annotation này được dùng để chỉ định tên column của table.
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Column(name = "employee_name")
private String employeeName;
}
@Id: Annotation này chỉ định khóa chính của entity.
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
private int id;
}
@GeneratedValue: Annotation này chỉ định các chiến lược tạo giá trị cho các khóa chính.
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy=SEQUENCE, generator="ID_SEQ")
private int id;
}
@Version: Chúng ta có thể kiểm soát phiên bản hoặc concurrency bằng cách sử dụng annotation này.
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Version
@Column(name = "version")
private Date version;
}
@OrderBy: Sắp xếp dữ liệu của bạn bằng cách sử dụng annotation@OrderBy. Trong ví dụ bên dưới, nó sẽ sắp xếp tất cảemployees_addresstheo id của chúng theo thứ tự tăng dần.
@OrderBy("id asc")
private Set employee_address;
@Transient: Mọi thuộc tínhnon staticvànon-transientcủa một entity đều được coi là persistent (bền vững), trừ khi bạn chú thích nó là@Transient.
@Transient
Private int employeePhone;
@Lob: Các Large objects được khai báo với@Lob.
@Lob
public String getEmployeeAddress() {
return employeeAddress;
}
Tập hợp annotations trên là những JPA annotations được sử dụng phổ biến nhất để xác định một entity.
Hibernate Annotations để ánh xạ giữa các Tables
Chúng ta có một tập hợp các annotations khác được dùng để chỉ định ánh xạ liên kết giữa các tables và entities khác nhau. Chúng ta sẽ lấy một ví dụ xem xét tình huống được đề cập dưới đây.
- Các tables ’employee’ và ’employeeDetail’ có mối liên kết một-một (
one-to-one association) và chúng dùng chung khóa chính. - Các tables ‘communication’ và ‘communicationDetail’ được liên kết bằng một foreign key (khóa ngoại). Nó cũng là một liên kết một-một.
- Các tables ‘communication’ và ’employee’ được liên kết bằng cách sử dụng một foreign key trong một liên kết nhiều-một với
communicationlà chủ sở hữu. - Các tables ’employee’ và ’employeeStatus’ được liên kết thông qua một foreign key trong liên kết nhiều-một với
employeelà chủ sở hữu.
@OneToOne: Các entities Employee và EmployeeDetail dùng chung khóa chính và chúng ta có thể liên kết chúng bằng cách sử dụng @OneToOne và @PrimaryKeyJoinColumn. Trong trường hợp này, thuộc tính id của EmployeeDetail không được chú thích với @GeneratedValue. Giá trị id của Employee sẽ được sử dụng cho id của EmployeeDetail.
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@Entity
@Table(name = "employeeDetail")
public class EmployeeDetail implements Serializable {
@Id
@Column(name = "id")
private int id;
}
Lưu ý:
@PrimaryKeyJoinColumnnên được sử dụng cho các entities liên kết chia sẻ cùng một khóa chính.@JoinColumn&@OneToOnenên đượcmappedBy attributekhi khóa ngoại được giữ bởi một trong các entities.
Communication và CommunicationDetail được liên kết thông qua một khóa ngoại, vì vậy annotations @OneToOne và @JoinColumn có thể được sử dụng. Trong đoạn mã được đề cập dưới đây, id được tạo cho Communication sẽ được ánh xạ tới column ‘communication_id’ của table CommunicationDetail. @MapsId được sử dụng cho mục đích này.
@Entity
@Table(name = "communicationDetail")
public class CommunicationDetail implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
}
@Entity
@Table(name = "communication")
public class Communication implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue
private Integer id;
@OneToOne(mappedBy = "communication", cascade = CascadeType.ALL)
private CommunicationDetail communicationDetail;
}
@ManyToOne: Nhiều nhân viên có thể dùng chung một trạng thái. Vì vậy, mối quan hệ employee với employeeStatus là mối quan hệ nhiều-một. Annotation @ManyToOne có thể được sử dụng cho mục đích này.
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
}
@OneToMany: Employee tới Communication sẽ là một mối quan hệ một-nhiều. Chủ sở hữu của mối quan hệ này là Communication, vì vậy, chúng ta sẽ sử dụng thuộc tính mappedBy trong Employee để biến nó thành một mối quan hệ hai chiều.
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@OneToMany(mappedBy = "employee", fetch = FetchType.EAGER)
@OrderBy("firstName asc")
private Set communications;
}
@PrimaryKeyJoinColumn: Annotation này được dùng để liên kết các entities dùng chung khóa chính.
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue
private int id;
@OneToOne(cascade = CascadeType.MERGE)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
}
@JoinColumn: Annotation @JoinColumn được sử dụng cho các liên kết một-một hoặc nhiều-một khi khóa ngoại được giữ bởi một trong các entities.
@ManyToOne
@JoinColumn(name = "statusId")
private EmployeeStatus status;
@JoinTable: @JoinTable và mappedBy nên được sử dụng cho các entities được liên kết thông qua một association table (bảng liên kết).
@OneToOne
@MapsId
@JoinColumn(name = "communicationId")
private Communication communication;
Hibernate Annotations cho ánh xạ Inheritance
Bây giờ chúng ta hãy cố gắng hiểu annotation ánh xạ inheritance (kế thừa) trong Hibernate. Hibernate hỗ trợ ba chiến lược ánh xạ inheritance cơ bản:
- table per class hierarchy
- table per subclass
- table per concrete class
Chúng ta sẽ xem xét ví dụ cho từng loại.
- Table per class hierarchy – chiến lược một bảng cho mỗi phân cấp class (
single table per Class Hierarchy Strategy).
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="cartype", discriminatorType=DiscriminatorType.STRING )
@DiscriminatorValue("Car")
public class Car { }
@Entity
@DiscriminatorValue("BMW")
public class BMW extends Car { }
- Table per class/subclass – joined subclass Strategy.
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Ship implements Serializable {}
@Entity
@PrimaryKeyJoinColumn
public class Titanic extends Ship {}
- Table per concrete class.
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Aeroplane implements Serializable {}
@DiscriminatorColumn: Như tên gọi, column này là discriminator và annotation này chỉ định discriminator column cho các chiến lược ánh xạ inheritance SINGLE_TABLE và JOINED.
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="cartype", discriminatorType=DiscriminatorType.STRING )
Đó là tất cả về JPA và Hibernate annotations. Tham khảo: JSR 338, Hibernate API Docs.