實體和數據庫之間存在某種映射關系,hibernate根據這種映射關系完成數據的存取。在程序中這種映射關系由映射文件(*.hbm.xml)或者java注解(@)定義。
本文以java注解的形式總結映射關系配置。
一、導入依賴包。
hibernate-distribution-3.6.5.Final-dist\hibernate-distribution-3.6.5.Final\lib\jpa 目錄下的 hibernate-jpa-2.0-api-1.0.0.Final.jar
二、新建實體類

package com.souvc.domain.user; import java.util.Date; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.springframework.format.annotation.DateTimeFormat; /** * 類名: UserLoginLog * 描述: 用戶登錄記錄表類 * 開發人員: souvc * 創建時間: 2015-9-7 * @version V3.0 */ @Entity @Table(name = "user_login_log") public class UserLoginLog implements java.io.Serializable { private static final long serialVersionUID = 8686390190132322570L; private Integer loginId; private String ip; private String address; private Integer type; private Integer status; @DateTimeFormat( pattern = "yyyy-MM-dd HH:mm:ss" ) private Date loginTime; //private UserBaseInfo userBaseInfo; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "login_id", unique = true, nullable = false) public Integer getLoginId() { return loginId; } public void setLoginId(Integer loginId) { this.loginId = loginId; } @Column(name = "ip", nullable = true) public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } @Column(name = "address", nullable = true) public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Column(name = "type", nullable = false) public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } @Column(name = "status", nullable = false) public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } @Column(name = "login_time", nullable = true) @Temporal(TemporalType.TIMESTAMP) public Date getLoginTime() { return loginTime; } public void setLoginTime(Date loginTime) { this.loginTime = loginTime; } // @ManyToOne(cascade = CascadeType.REFRESH, optional = false) // @JoinColumn(name = "user_id", unique = true) // public UserBaseInfo getUserBaseInfo() { // return userBaseInfo; // } // // public void setUserBaseInfo(UserBaseInfo userBaseInfo) { // this.userBaseInfo = userBaseInfo; // } }
三、具體注解解釋
實體類組件以及注解標簽映射關系
實體類-----------@Entity/@Table----------數據表
Id--------------@Id----------主鍵
普通屬性---------@Column----------普通鍵
集合屬性---------@OneToMany/@ManyToOne/@ManyToMany/@OneToOne----------外鍵
A.寫在類聲明之前的有:
a.@Entity,以表明此Bean為EntityBean。每一個持久化POJO類都是一個實體bean,這可以通過在類的定義中使用@Entity注解來進行聲明。name 為可選 , 對應數據庫中一的個表
b.@Table (name=”TableName”),表示此實體Bean對應的數據庫表名。
@Table是類一級的注解, 通過@Table注解可以為實體bean映射指定表(table),目錄(catalog)和schema的名字.
如果沒有定義@Table,那么系統自動使用默認值:實體的短類名(不附帶包名).@Table元素包括了一個schema 和一個 catalog屬性,如果需要可以指定相應的值. 結合使用@UniqueConstraint注解可以定義表的唯一約束(unique constraint)
B.寫在getXxx()方法聲明之前的有:
a.@Column注釋定義了映射到列的所有屬性,如列名是否唯一,是否允許為空,是否允許更新等,他的屬性介紹如下:
(1) name 可選,列名(默認值是屬性名) (2) unique 可選,是否在該列上設置唯一約束(默認值false) (3) nullable 可選,是否設置該列的值可以為空(默認值false) (4) insertable 可選,該列是否作為生成的insert語句中的一個列(默認值true) (5) updatable 可選,該列是否作為生成的update語句中的一個列(默認值true) (6) columnDefinition 可選: 為這個特定列覆蓋SQL DDL片段 (這可能導致無法在不同數據庫間移植) (7) table 可選,定義對應的表(默認為主表) (8) length 可選,列長度(默認值255) (8) precision 可選,列十進制精度(decimal precision)(默認值0) (10) scale 可選,如果列十進制數值范圍(decimal scale)可用,在此設置(默認值0)
b.@Id 注釋指定personid屬性為表的主鍵,它可以有多種生成方式:
@id 定義了映射到數據庫表的主鍵的屬性 , 一個實體只能有一個屬性被映射為主鍵 . 置於 getXxxx() 前 .

·TABLE:容器指定用底層的數據表確保唯一。
·SEQUENCE:使用數據庫的SEQUENCE 列來保證唯一
·IDENTITY:使用數據庫的INDENTIT列來保證唯一
·AUTO:由容器挑選一個合適的方式來保證唯一
·NONE:容器不負責主鍵的生成,由調用程序來完成。
c.@GeneratedValue注釋定義標識字段的生成方式。
@GeneratedValue(strategy=GenerationType,generator="")
strategy: 表示主鍵生成策略 , 有 AUTO,INDENTITY,SEQUENCE 和 TABLE 4 種 , 分別表示讓 ORM 框架自動選擇, 根據數據庫的 Identity 字段生成 ,
根據數據庫表的 Sequence 字段生成 ,
以有根據一個額外的表生成主鍵 , 默認為AUTO generator: 表示主鍵生成器的名稱 , 這個屬性通常和 ORM 框架相關 , 例如 ,Hibernate 可以指定 uuid 等主鍵生成方式 . 示例 : @Id @GeneratedValues(strategy=StrategyType.SEQUENCE) public int getPk() { return pk; }
d. @Version 映射版本號屬性
e. @Column 指定屬性對應的列的信息
可選 @Column 描述了數據庫表中該字段的詳細定義 , 這對於根據 JPA 注解生成數據庫表結構的工具非常有作用 . name: 表示數據庫表中該字段的名稱 , 默認情形屬性名稱一致 nullable: 表示該字段是否允許為 null, 默認為 true unique: 表示該字段是否是唯一標識 , 默認為 false length: 表示該字段的大小 , 僅對 String 類型的字段有效 insertable: 表示在 ORM 框架執行插入操作時 , 該字段是否應出現 INSETRT 語句中 , 默認為 true updateable: 表示在 ORM 框架執行更新操作時 , 該字段是否應該出現在 UPDATE 語句中 , 默認為 true. 對於一經創建就不可以更改的字段 , 該屬性非常有用 , 如對於 birthday 字段 . columnDefinition: 表示該字段在數據庫中的實際類型 . 通常 ORM 框架可以根據屬性類型自動判斷數據庫中字段的類型 , 但是對於 Date 類型仍無法確定數據庫中字段類型究竟是 DATE,TIME 還是 TIMESTAMP. 此外 ,String 的默認映射類型為 VARCHAR, 如果要將 String 類型映射到特定數據庫的 BLOB 或 TEXT 字段類型 , 該屬性非常有用 . 示例 : @Column(name="BIRTH",nullable="false",columnDefinition="DATE") public String getBithday() { return birthday; }
f . @Temporal 指定日期時間的類型(TIMESTAMP,DATE,TIME)
g. 簡單屬性可以不用注解。默認就是@Basic
h. @Transient 指定屬性不需要映射
可選 @Transient 表示該屬性並非一個到數據庫表的字段的映射 ,ORM 框架將忽略該屬性 . 如果一個屬性並非數據庫表的字段映射 , 就務必將其標示為 @Transient, 否則 ,ORM 框架默認其注解為 @Basic 示例 : // 根據 birth 計算出 age 屬性 @Transient public int getAge() { return getYear(new Date()) - getYear(birth); }
i. 復雜屬性:關聯,繼承,組件,聯合主鍵,集合
C.關系/對象映射
A.一對多:
@OneToMany指明關聯關系為一對多關系,下面是@OneToMany 注釋的屬性:
1>targetEntity
Class 類型的屬性。定義關系類的類型,默認是該成員屬性對應的類類型,所以通常不需要提供定義。
2>mappedBy
String 類型的屬性。定義類之間的雙向關系。如果類之間是單向關系,不需要提供定義,如果類和類之間形成雙向關系,我們就需要使用這個屬性進行定義,否則可能引起數據一致性的問題。
3>cascade
CascadeType[]類型。
該屬性定義類和類之間的級聯關系。定義的級聯關系將被容器視為對當前類對象及其關聯類對象采取相同的操作,而且這種關系是遞歸調用的。
舉個例 子:Order 和OrderItem 有級聯關系,那么刪除Order 時將同時刪除它所對應的OrderItem對象。而如果OrderItem還和其他的對象之間有級聯關系,那么這樣的操作會一直遞歸執行下去。
cascade 的值只能從:
CascadeType.PERSIST(級聯新建);
CascadeType.REMOVE(級聯刪除);
CascadeType.REFRESH(級聯刷新);
CascadeType.MERGE(級聯更新)中選擇一個或多個。
還有一個選擇是使用CascadeType.ALL,表示選擇全部四項。
4>fatch
FetchType 類型的屬性。
可選擇項包括:FetchType.EAGER和FetchType.LAZY。
前者表示關系類(本例是OrderItem類)在主類(本例是Order類)加載的時候同時加載;
后者表示關系類在被訪問時才加載。默認值是FetchType. LAZY。
@OrderBy(value = "id ASC")注釋指明加載OrderItem 時按id 的升序排序。
B.多對一:
@ManyToOne注釋,有四個屬性:targetEntity、cascade、fetch 和optional。
前三個屬性的具體含義和@OneToMany注釋的同名屬性相同,但@ManyToOne 注釋的fetch 屬性默認值是FetchType.EAGER。
optional 屬性是定義該關聯類對是否必須存在,值為false 時,關聯類雙方都必須存在,如果關系被維護端不存在,查詢的結果為null。值為true 時, 關系被維護端可以不存在,查詢的結果仍然會返回關系維護端,在關系維護端中指向關系被維護端的屬性為null。
optional屬性的默認值是true。
舉個例:某項訂單(Order)中沒有訂單項(OrderItem),如果optional 屬性設置為false,獲取該項訂單(Order)時,得到的結果為null,如果optional屬性設置為true,仍然可以獲取該項訂單,但訂單中 指向訂單項的屬性為null。
實際上在解釋Order 與OrderItem的關系成SQL時,optional屬性指定了他們的聯接關系
optional=false 聯接關系為inner join,
optional=true 聯接關系為left join。
@JoinColumn(name = "order_id")注釋指定OrderItem 映射表的order_id 列作為外鍵與Order 映射表的主鍵列關聯。
可選 @ManyToOne 表示一個多對一的映射 , 該注解標注的屬性通常是數據庫表的外鍵 optional: 是否允許該字段為 null, 該屬性應該根據數據庫表的外鍵約束來確定 , 默認為 true fetch: 表示抓取策略 , 默認為 FetchType.EAGER cascade: 表示默認的級聯操作策略 , 可以指定為 ALL,PERSIST,MERGE,REFRESH 和 REMOVE 中的若干組合 , 默認為無級聯操作 targetEntity: 表示該屬性關聯的實體類型 . 該屬性通常不必指定 ,ORM 框架根據屬性類型自動判斷targetEntity. 示例 : // 訂單 Order 和用戶 User 是一個 ManyToOne 的關系 // 在 Order 類中定義 @ManyToOne() @JoinColumn(name="USER") public User getUser() { return user; }
C.一對一:
@OneToOne 注釋,有五個屬性:targetEntity、cascade、fetch、optional 和mappedBy 。
前四個屬性的具體含義與@ManyToOne 注釋的同名屬性一一對應, fetch 屬性默認值是FetchType.EAGER。
mappedBy屬性的具體含義與@OneToMany 注釋的同名屬性相同。
如果optional = true 設置表明此屬性可以為null。
例如在身份證的處理時可以這樣設置,因為未成年人就是沒有身份證的。
D.多對多:
@ManyToMany 注釋:表示此類是多對多關系的一邊,mappedBy 屬性定義了此類為雙向關系的維護端,注意:mappedBy 屬性的值為此關系的另一端的屬性名。
例如,在Student類中有如下方法:
@ManyToMany(mappedBy = "students") public Set<Teacher> getTeachers() { return teachers; }
那么這里的“students”就是Teachers的一個屬性,通常應該是這樣的:
Set<Student> students;
另一端的getStudents方法如下所示:
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY) @JoinTable(name = "Teacher_Student",joinColumns = {@JoinColumn(name = "Teacher_ID", referencedColumnName = "teacherid")},inverseJoinColumns = {@JoinColumn(name = "Student_ID", referencedColumnName ="studentid")}) public Set<Student> getStudents() { return students; }
@ManyToMany 注釋表示Teacher 是多對多關系的一端。
@JoinTable 描述了多對多關系的數據表關系。
name 屬性指定中間表名稱,joinColumns 定義中間表與Teacher 表的外鍵關系。
上面的代碼中,中間表Teacher_Student的Teacher_ID 列是Teacher 表的主鍵列對應的外鍵列,inverseJoinColumns 屬性定義了中間表與另外一端(Student)的外鍵關系。
可以參照中文官方文檔: http://docs.jboss.org/hibernate/annotations/3.4/reference/zh_cn/html_single/