前言
本期我們對Hibernate JPA注解的配置進行說明,這些注解如何使用,如何配置等。
@Table
Table 用來定義 entity 主表的 name,catalog,schema 等屬性。
屬性說明:
- name:表名
- catalog:對應(yīng)數(shù)據(jù)庫的catalog
- schema:對應(yīng)關(guān)系數(shù)據(jù)庫中的schema
- UniqueConstraints:定義一個 UniqueConstraint 數(shù)組,指定需要建唯一約束的列
@Entity
@Table(name="CUST")
public class Customer { ... }
@SecondaryTable
一個 entity class 可以映射到多表,SecondaryTable 用來定義單個從表的名字,主鍵名字等屬性。
屬性說明:
- name:表名
- catalog:對應(yīng)關(guān)系數(shù)據(jù)庫中的 catalog
- pkJoin:定義一個 PrimaryKeyJoinColumn 數(shù)組,指定從表的主鍵列
- UniqueConstraints:定義一個 UniqueConstraint 數(shù)組,指定需要建唯一約束的列
下面的代碼說明 Customer 類映射到兩個表,主表名是 CUSTOMER,從表名是CUST_DETAIL,從表的主鍵列和主表的主鍵列類型相同,列名為 CUST_ID。
@Entity
@Table(name="CUSTOMER")
@SecondaryTable(name="CUST_DETAIL",pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
public class Customer { ... }
@SecondaryTables
當(dāng)一個 entity class 映射到一個主表和多個從表時,用 SecondaryTables 來定義各個從表的屬性。
屬性說明:
- value:定義一個 SecondaryTable 數(shù)組,指定每個從表的屬性。
@Table(name = "CUSTOMER")
@SecondaryTables( value = {
@SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }),
@SecondaryTable(name = "CUST_ADDRESS", pkJoin = { @PrimaryKeyJoinColumn(name = "STMO_ID", referencedColumnName = "id") }) })
public class Customer {}
@UniqueConstraint
UniqueConstraint 定義在 Table 或 SecondaryTable 元數(shù)據(jù)里,用來指定建表時需要建唯一約束的列。
屬性說明:
- columnNames:定義一個字符串?dāng)?shù)組,指定要建唯一約束的列名。
@Entity
@Table(name="EMPLOYEE",uniqueConstraints={@UniqueConstraint(columnNames={"EMP_ID","EMP_NAME"})})
public class Employee { ... }
@Column
Column 元數(shù)據(jù)定義了映射到數(shù)據(jù)庫的列的所有屬性:列名,是否唯一,是否允許為空,是否允許更新等。
屬性說明:
- unique:是否唯一
- nullable:是否允許為空
- insertable:是否允許插入
- updatable:是否允許更新
- columnDefinition:定義建表時創(chuàng)建此列的 DDL
- secondaryTable:從表名。如果此列不建在主表上(默認建在主表),該屬性定義該列所在從表的名字。
public class Person {
@Column(name = "PERSONNAME", unique = true, nullable = false, updatable = true)
private String name;
@Column(name = "PHOTO", columnDefinition = "BLOB NOT NULL", secondaryTable="PER_PHOTO")
private byte[] picture;
}
@JoinColumn
如果在 entity class 的 field 上定義了關(guān)系(one2one 或 one2many 等),我們通過 JoinColumn來定義關(guān)系的屬性。JoinColumn 的大部分屬性和 Column 類似。
屬性說明:
- name:另一個表指向本表的外鍵
- unique:是否唯一
- referencedColumnName:該列指向列的列名(建表時該列作為外鍵列指向關(guān)系另一端的指定列)
- nullable:是否允許為空
- insertable:是否允許插入
- updatable:是否允許更新
- columnDefinition:定義建表時創(chuàng)建此列的 DDL
- secondaryTable:從表名。如果此列不建在主表上(默認建在主表),該屬性定義該
列所在從表的名字。
下面的代碼說明 Custom 和 Order 是一對一關(guān)系。在 Order 對應(yīng)的映射表建一個名為CUST_ID 的列,該列作為外鍵指向 Custom 對應(yīng)表中名為 ID 的列。
public class Custom {
@OneToOne
@JoinColumn(name = "CUST_ID", referencedColumnName = "ID", unique = true, nullable = true, updatable = true)
public Order getOrder() {
return order;
}
}
@JoinColumns
如果在 entity class 的 field 上定義了關(guān)系(one2one 或 one2many 等),并且關(guān)系存在多個 JoinColumn,用 JoinColumns 定義多個 JoinColumn 的屬性。
屬性說明:
- value:定義 JoinColumn 數(shù)組,指定每個 JoinColumn 的屬性。
下面的代碼說明 Custom 和 Order 是一對一關(guān)系。在 Order 對應(yīng)的映射表建兩列,一列名為CUST_ID,該列作為外鍵指向Custom對應(yīng)表中名為ID的列,另一列名為CUST_NAME,該列作為外鍵指向 Custom 對應(yīng)表中名為 NAME 的列。
public class Custom {
@OneToOne
@JoinColumns({
@JoinColumn(name = "CUST_ID", referencedColumnName = "ID"),
@JoinColumn(name = "CUST_NAME", referencedColumnName = "NAME")
})
public Order getOrder() {
return order;
}
}
@Id
聲明當(dāng)前 field 為映射表中的主鍵列。id 值的獲取方式有五種:TABLE, SEQUENCE,IDENTITY, AUTO, NONE。Oracle 和 DB2 支持 SEQUENCE,SQL Server 和 Sybase 支持 IDENTITY,mysql 支持 AUTO。所有的數(shù)據(jù)庫都可以指定為 AUTO,我們會根據(jù)不同數(shù)據(jù)庫做轉(zhuǎn)換。NONE(默認)需要用戶自己指定 Id 的值。
屬性說明:
- generate:主鍵值的獲取類型
- generator:TableGenerator 的名字(當(dāng) generate=GeneratorType.TABLE 才需要指定
該屬性)
下面的代碼聲明 Task 的主鍵列 id 是自動增長的。(Oracle 和 DB2 從默認的 SEQUENCE取值,SQL Server 和 Sybase 該列建成 IDENTITY,mysql 該列建成 auto increment。)
@Entity
@Table(name = "OTASK")
public class Task {
@Id(generate = GeneratorType.AUTO)
public Integer getId() {
return id;
}
}
@IdClass
當(dāng) entity class 使用復(fù)合主鍵時,需要定義一個類作為 id class。id class 必須符合以下要求:類必須聲明為 public,并提供一個聲明為 public 的空構(gòu)造函數(shù)。必須實現(xiàn) Serializable 接,覆寫 equals()和 hashCode()方法。entity class 的所有 id field 在 id class 都要定義,且類型一樣。
屬性說明:
- value:id class 的類名
下面的代碼聲明 Task 的主鍵列 id 是自動增長的。(Oracle 和 DB2 從默認的 SEQUENCE取值,SQL Server 和 Sybase 該列建成 IDENTITY,mysql 該列建成 auto increment。)
public class EmployeePK implements java.io.Serializable {
String empName;
Integer empAge;
public EmployeePK() {
}
public boolean equals(Object obj) { ......}
public int hashCode() {......}
}
@IdClass(value = com.acme.EmployeePK.class)
@Entity(access = FIELD)
public class Employee {
@Id
String empName;
@Id
Integer empAge;
}
@MapKey
在一對多,多對多關(guān)系中,我們可以用 Map 來保存集合對象。默認用主鍵值做 key,如果使用復(fù)合主鍵,則用 id class 的實例做 key,如果指定了 name 屬性,就用指定的 field 的值做 key。
屬性說明:
- name:用來做 key 的 field 名字
下面的代碼說明 Person 和 Book 之間是一對多關(guān)系。Person 的 books 字段是 Map 類型,用 Book 的 isbn 字段的值作為 Map 的 key。
@Table(name = "PERSON")
public class Person {
@OneToMany(targetEntity = Book.class, cascade = CascadeType.ALL, mappedy = "person")
@MapKey(name = "isbn")
private Map books = new HashMap();
}
@MappedSuperclass
使用@MappedSuperclass 指定一個實體類從中繼承持久字段的超類。當(dāng)多個實體類共享通用的持久字段或?qū)傩詴r,這將是一個方便的模式。
您可以像對實體那樣使用任何直接和關(guān)系映射批注(如 @Basic 和 @ManyToMany)對該超類的字段和屬性進行批注,但由于沒有針對該超類本身的表存在,因此這些映射只適用于它的子類。繼承的持久字段或?qū)傩詫儆谧宇惖谋怼?/p>
可以在子類中使用@AttributeOverride 或@AssociationOverride 來覆蓋超類的映射配置。
@MappedSuperclass 沒有屬性。
//如何將 Employee 指定為映射超類
@MappedSuperclass
public class Employee {
@Id
protected Integer empId;
@Version
protected Integer version;
@ManyToOne
@JoinColumn(name = "ADDR")
protected Address address;
}
//如何在實體類中使用@AttributeOverride 以覆蓋超類中設(shè)置的配置。
@Entity
@AttributeOverride(name = "address", column = @Column(name = "ADDR_ID"))
public class PartTimeEmployee extends Employee {
@Column(name = "WAGE")
protected Float hourlyWage;
}
@PrimaryKeyJoinColumn
在三種情況下會用到@PrimaryKeyJoinColumn
- 繼承。
- entity class 映射到一個或多個從表。從表根據(jù)主表的主鍵列(列名為referencedColumnName 值的列),建立一個類型一樣的主鍵列,列名由 name 屬性定義。
- one2one 關(guān)系,關(guān)系維護端的主鍵作為外鍵指向關(guān)系被維護端的主鍵,不再新建一個外鍵列。
屬性說明:
- name:列名。
- referencedColumnName:該列引用列的列名
- columnDefinition:定義建表時創(chuàng)建此列的 DDL
下面的代碼說明 Customer 映射到兩個表,主表 CUSTOMER,從表 CUST_DETAIL,從表需要建立主鍵列 CUST_ID,該列和主表的主鍵列 id 除了列名不同,其他定義一樣。
@Entity
@Table(name = "CUSTOMER")
@SecondaryTable(name = "CUST_DETAIL", pkJoin = @PrimaryKeyJoinColumn(name = "CUST_ID",referencedColumnName = " id"))
public class Customer {
@Id(generate = GeneratorType.AUTO)
public Integer getId() {
return id;
}
}
下面的代碼說明 Employee 和 EmployeeInfo 是一對一關(guān)系,Employee 的主鍵列 id 作為外鍵指向 EmployeeInfo 的主鍵列 INFO_ID。
@Table(name = "Employee")
public class Employee {
@OneToOne
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "INFO_ID")
EmployeeInfo info;
}
@PrimaryKeyJoinColumns
如果 entity class 使用了復(fù)合主鍵,指定單個 PrimaryKeyJoinColumn 不能滿足要求時,可
以用 PrimaryKeyJoinColumns 來定義多個 PrimaryKeyJoinColumn
屬性說明:
- value: 一個 PrimaryKeyJoinColumn 數(shù)組,包含所有 PrimaryKeyJoinColumn下面的代碼說明了 Employee 和 EmployeeInfo 是一對一關(guān)系。他們都使用復(fù)合主鍵,建表時需要在 Employee 表建立一個外鍵,從 Employee 的主鍵列 id,name 指向 EmployeeInfo的主鍵列 INFO_ID 和 INFO_NAME
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE")
public class Employee {
private int id;
private String name;
private String address;
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumns
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "INFO_ID")
@PrimaryKeyJoinColumn(name = "name", referencedColumnName = "INFO_NAME") })
EmployeeInfo info;
}
@Entity
@IdClass(EmpPK.class)
@Table(name = "EMPLOYEE_INFO")
public class EmployeeInfo {
@Id
@Column(name = "INFO_ID")
private int id;
@Id
@Column(name = "INFO_NAME")
private String name;
}
@Transient
Transient 用來注釋 entity 的屬性,指定的這些屬性不會被持久化,也不會為這些屬性建表
@Transient
private String name;
@Version
Version 指定實體類在樂觀事務(wù)中的 version 屬性。在實體類重新由 EntityManager 管理并
且加入到樂觀事務(wù)中時,保證完整性。每一個類只能有一個屬性被指定為 version,version
屬性應(yīng)該映射到實體類的主表上。
屬性說明:
- value: 一個 PrimaryKeyJoinColumn 數(shù)組,包含所有 PrimaryKeyJoinColumn下面的代碼說明 versionNum 屬性作為這個類的 version,映射到數(shù)據(jù)庫中主表的列名是OPTLOCK
@Version
@Column("OPTLOCK")
protected int getVersionNum() { return versionNum; }