在Hibernate中一般配置對象關係映射關係有兩種,一種是基於xml的方式,另外一種是基於Hibernate Annotation庫的註解方式。在Hibernate 3.2版本和Java 5 環境下開始支持使用註解配置對象關係映射,使用Hibernate註解以後,可不用定義持久化類所對應的*.hbm.xml文件,直接用註解的方式寫入持久化類中實現html
兩種方法要注意的兩個不一樣處:
(1):hibernate.hbm.xml 文件中把引用:xxx.hbm.xml改成引用實體類:java
即把
<mapping resource="com/wsw/hibernate/model/Person.hbm.xml"/>
改成:<mapping class="com.wsw.hibernate.model.Teacher" />
數據庫
(2):獲取SessionFactory方式發生了變化:數組
即把
SessionFactorysf=newConfiguration().configure().buildSessionFactory()
改成SessionFactory sf=new AnnotationConfiguration().configure().buildSessionFactory()
app
在屬性註解使用上,您既能夠保持字段的持久性(註解寫在成員變量之上),也能夠保持屬性(註解寫在getter方法之上)的持久性,但建議不要在屬性上引入註解,由於屬性是private的,若是引入註解會破壞其封裝特性,因此建議在getter方法上加入註解框架
@Entityfetch
將一個Javabean類聲明爲一個實體的數據庫表映射類,最好實現序列化。默認狀況下,全部的類屬性都爲映射到數據表的持久性字段。若在類中有屬性不映射到數據庫中的,要用下面的@Transient來註解。ui
*屬性:* `name` - 可選,對應數據庫中的一個表。若表名與實體類名相同,則能夠省略。@Table
在@Entity下使用,表示實體對應數據庫中的表的信息this
屬性:name
- 可選,表示表的名稱,默認表名和實體名稱一致,不一致的狀況下需指定表名。catalog
- 可選,表示Catalog名稱,默認爲 Catalog("")schema
- 可選 , 表示 Schema 名稱 , 默認爲Schema("").net
@Entity() @Table(name="Student") public class Student implements Serializable{ }
@Id
必須,定義了映射到數據庫表的主鍵的屬性,一個實體只能有一個屬性被映射爲主鍵
@GeneratedValue
定義自動增加的主鍵的生成策略.
屬性:strategy
- 表示主鍵生成策略,取值有如下
GenerationType.AUTO 根據底層數據庫自動選擇(默認),若數據庫支持自動增加>類型,則爲自動增加。 GenerationType.INDENTITY 根據數據庫的Identity字段生成,支持DB二、MySQL、MS、SQL Server、SyBase與HyperanoicSQL數據庫的Identity GenerationType.SEQUENCE 使用Sequence來決定主鍵的取值,適合Oracle、DB2等支持Sequence的數據庫,通常結合@SequenceGenerator使用。(Oracle沒有自動增加類型,只能用Sequence) GenerationType.TABLE 使用指定表來決定主鍵取值,結合@TableGenerator使用。
@Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int sid;
GenerationType.TABLE的使用
@Id @GeneratedValue(strategy=GenerationType.TABLE,generator="strategyName") @TableGenerator( name = "strategyName", // 主鍵生成策略的名稱,它被引用在@GeneratedValue中設置的「generator」值中 table="", //表示表生成策略所持久化的表名 catalog="", //表所在的目錄名 schema="", //數據庫名 pkColumnName="", //在持久化表中,該主鍵生成策略所對應鍵值的名稱 valueColumnName="", //表示在持久化表中,該主鍵當前所生成的值,它的值將會隨着每次建立累加 pkColumnValue="", //表示在持久化表中,該生成策略所對應的主鍵 allocationSize=1 //表示每次主鍵值增長的大小,例如設置成1,則表示每次建立新記錄後自動加1,默認爲50 )
GenerationType.SEQUENCE的使用
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE,generator="strategyName") @SequenceGenerator( name="strategyName", //name屬性表示該表主鍵生成策略的名稱,它被引用在@GeneratedValue中設置的「generator」值中 sequenceName="" //表示生成策略用到的數據庫序列名稱 )
@Transient
將忽略這些字段和屬性,不用持久化到數據庫。
@Column
可將屬性映射到列,使用該註解來覆蓋默認值
屬性:name
- 可選,表示數據庫表中該字段的名稱,默認情形屬性名稱一致
length
- 可選,表示該字段的大小,僅對 String 類型的字段有效,默認值255.insertable
- 可選,表示在ORM框架執行插入操做時,該字段是否應出現INSETRT 語句中,默認爲 trueupdateable
- 可選,表示在ORM 框架執行更新操做時,該字段是否應該出如今 UPDATE 語句中,默認爲 true. 對於一經建立就不能夠更改的字段,該屬性很是有用,如對於 birthday 字段。columnDefinition
- 可選,表示該字段在數據庫中的實際類型。一般ORM 框架能夠根 據屬性類型自動判斷數據庫中字段的類型,可是對於Date 類型仍沒法肯定數據庫中字段類型到底是 DATE,TIME 仍是 TIMESTAMP. 此外 ,String 的默認映射類型爲 VARCHAR, 若是要將 String 類型映射到特定數據庫的 BLOB或 TEXT 字段類型,該屬性很是有用。
@Version
聲明添加對樂觀鎖定的支持
一些屬性
fetch
關聯關係獲取方式,便是否採用延時加載
Fetch.EAGER - 及時加載,是在查詢數據時,也直接一塊兒獲取關聯對象的數據。多對一默認是Fetch.EAGER
Fetch.LAZY -延遲加載,查詢數據時,不一塊兒查詢關聯對象的數據。而是當訪問關聯對象時才觸發相應的查詢操做,獲取關聯對象數據。一對多默認是Fetch.LAZY
cascade
設置級聯方式
CascadeType.PERSIST 保存
CascadeType.REMOVE - 刪除
CascadeType.MERGE 修改
CascadeType.REFRESH 刷新
CascadeType.ALL - 所有
mappedBy
mappedBy指的是多方對一方的依賴的屬性,(注意:若是沒有指定由誰來維護關聯關係,則系統會給咱們建立一張中間表)。
若是這個一對多的關係不是經過第三張表來維持,而是多方保存一方的id(多方外鍵引用一方),則必需要有mappedBy來指明多方中哪一個變量來保存一方(外鍵),值是多方里面保存一方的屬性名字
在判斷究竟是誰維護關聯關係時,能夠經過查看外鍵,哪一個實體類定義了外鍵,哪一個類就負責維護關聯關係mappedBy
至關於xml配置中的inverse="true"
@OneToMany
描述一個一對多的關聯,該屬性應該爲集合類型
@OneToMany
默認會使用鏈接表作一對多關聯
若是這個一對多的關係不是經過第三張表來維持,而是多方保存一方的id(多方外鍵引用一方),則必需要有mappedBy
來指明多方中哪一個變量來保存一方(外鍵),值是多方里面保存一方的屬性名字
@OneToMany(cascade={CascadeType.ALL},mappedBy="grade") public Set<Student> getStudents() { return students; }
@ManyToOne
表示一個多對一的映射,該註解標註的屬性一般是數據庫表的外鍵。 單向多對一關聯在多方:
@ManyToOne(targetEntity=XXXX.class) //指定關聯對象
@JoinColumn(name="") //指定產生的外鍵字段名
雙向一對多同雙向多對一
在多方
@ManyToOne
@JoinColumn(name="本身的數據庫外鍵列名")
在一方
@OneToMany(mappedBy="多端的關聯屬性名")
/* * 學生類負責關聯關係 */ @Entity @Table(name="Student") public class Student implements Serializable{ private int sid; private String sex; private String name; private Grade grade; public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } @Id @GenericGenerator(name="generator",strategy="native") @GeneratedValue(generator="generator") public int getId() { return sid; } public void setId(int id) { this.sid = id; } @Column(name="sex") public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @ManyToOne(cascade={CascadeType.ALL}) @JoinColumn(name="gid") public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; } }
/* * 班級類 */ @Entity @Table(name="Grade") public class Grade implements Serializable{ private int gid; private String name; private Set<Student> students=new HashSet<Student>(); public Grade() { } @Id @GenericGenerator(name="generator",strategy="native") @GeneratedValue(generator="generator") public int getGid() { return gid; } public void setGid(int gid) { this.gid = gid; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(cascade={CascadeType.ALL},mappedBy="grade") public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
在多對多關聯中,雙方都採用
@ManyToMany
. 其中被維護方mappedBy
表示由另外一多方維護
經過中間表由任一多方來維護關聯關係
其中主控方,不像一對多註解那樣,採用@joinColumn
,而是採用@joinTable
@JoinTable( name="student_course", joinColumns={@JoinColumn(name="")}, inverseJoinColumns={@JoinColumn(name="")} )
由於多對多之間會經過一張中間表來維護兩表直接的關係,因此經過
JoinTable
這個註解來聲明。name
就是指定了中間表的名字。JoinColumns
是一個@JoinColumn
類型的數組,表示的是我這方在對方中的外鍵名稱,就是當前類的主鍵。inverseJoinColumns
也是一個@JoinColumn類型的數組,表示的是對方在我這方中的外鍵名稱,也能夠這樣想:上面提到mappedBy
,至關於inverse="true"
.因此,在@joinTable
中的inverseJoinColumns
中定義的字段爲mappedBy
所在類的主鍵。
在前面的基礎上增長課程類並補充學生類
/* * 學生類負責關聯關係 */ @Entity @Table(name="Student") public class Student implements Serializable{ private int sid; private String name; private String sex; private Grade grade; private Set<Course> courses=new HashSet<Course>(); public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } @Id @GenericGenerator(name="generator",strategy="native") @GeneratedValue(generator="generator") public int getId() { return sid; } public void setId(int id) { this.sid = id; } @Column(name="sex") public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @ManyToOne(cascade={CascadeType.ALL}) @JoinColumn(name="gid") public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; } @ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER) @JoinTable(name="student_course",joinColumns={@JoinColumn(name="sid")},inverseJoinColumns={@JoinColumn(name="cid")}) public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } }
@Entity @Table(name="Course") public class Course implements Serializable{ private int cid; private String cName; private Set<Student> students=new HashSet<Student>(); public Course() { } @Id @GenericGenerator(name="generator",strategy="native") @GeneratedValue(generator="generator") public int getCid() { return cid; } public void setStudents(Set<Student> students) { this.students = students; } public void setCid(int cid) { this.cid = cid; } public String getcName() { return cName; } public void setcName(String cName) { this.cName = cName; } @ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY ,mappedBy="courses") public Set<Student> getStudents() { return students; } }