hibernate中@Entity和@Table的区别
Java?Persistence API定義了一種定義,可以將常規(guī)的普通Java對(duì)象(有時(shí)被稱(chēng)作POJO)映射到數(shù)據(jù)庫(kù)。
這些普通Java對(duì)象被稱(chēng)作Entity Bean。
除了是用Java Persistence元數(shù)據(jù)將其映射到數(shù)據(jù)庫(kù)外,Entity Bean與其他Java類(lèi)沒(méi)有任何區(qū)別。
事實(shí)上,創(chuàng)建一個(gè)Entity Bean對(duì)象相當(dāng)于新建一條記錄,刪除一個(gè)Entity Bean會(huì)同時(shí)從數(shù)據(jù)庫(kù)中刪除對(duì)應(yīng)記錄,修改一個(gè)Entity Bean時(shí),容器會(huì)自動(dòng)將Entity Bean的狀態(tài)和數(shù)據(jù)庫(kù)同步。
Java Persistence API還定義了一種查詢(xún)語(yǔ)言(JPQL),具有與SQL相類(lèi)似的特征,只不過(guò)做了裁減,以便處理Java對(duì)象而非原始的關(guān)系表。
?hibernate中@Entity和@Table的區(qū)別:
@Entity說(shuō)明這個(gè)class是實(shí)體類(lèi),并且使用默認(rèn)的orm規(guī)則,即class名即數(shù)據(jù)庫(kù)表中表名,class字段名即表中的字段名
如果想改變這種默認(rèn)的orm規(guī)則,就要使用@Table來(lái)改變class名與數(shù)據(jù)庫(kù)中表名的映射規(guī)則,@Column來(lái)改變class中字段名與db中表的字段名的映射規(guī)則
?
@Entity注釋指名這是一個(gè)實(shí)體Bean,@Table注釋指定了Entity所要映射帶數(shù)據(jù)庫(kù)表,其中@Table.name()用來(lái)指定映射表的表名。 如果缺省@Table注釋,系統(tǒng)默認(rèn)采用類(lèi)名作為映射表的表名。實(shí)體Bean的每個(gè)實(shí)例代表數(shù)據(jù)表中的一行數(shù)據(jù),行中的一列對(duì)應(yīng)實(shí)例中的一個(gè)屬性。@Column注釋定義了將成員屬性映射到關(guān)系表中的哪一列和該列的結(jié)構(gòu)信息,屬性如下: 1)name:映射的列名。如:映射tbl_user表的name列,可以在name屬性的上面或getName方法上面加入; 2)unique:是否唯一; 3)nullable:是否允許為空; 4)length:對(duì)于字符型列,length屬性指定列的最大字符長(zhǎng)度; 5)insertable:是否允許插入; 6)updatetable:是否允許更新; 7)columnDefinition:定義建表時(shí)創(chuàng)建此列的DDL; 8)secondaryTable:從表名。如果此列不建在主表上(默認(rèn)是主表),該屬性定義該列所在從表的名字。 @Id注釋指定表的主鍵,它可以有多種生成方式:1)TABLE:容器指定用底層的數(shù)據(jù)表確保唯一; 2)SEQUENCE:使用數(shù)據(jù)庫(kù)德SEQUENCE列萊保證唯一(Oracle數(shù)據(jù)庫(kù)通過(guò)序列來(lái)生成唯一ID); 3)IDENTITY:使用數(shù)據(jù)庫(kù)的IDENTITY列萊保證唯一; 4)AUTO:由容器挑選一個(gè)合適的方式來(lái)保證唯一; 5)NONE:容器不負(fù)責(zé)主鍵的生成,由程序來(lái)完成。@GeneratedValue注釋定義了標(biāo)識(shí)字段生成方式。@Temporal注釋用來(lái)指定java.util.Date或java.util.Calender屬性與數(shù)據(jù)庫(kù)類(lèi)型date、time或timestamp中的那一種類(lèi)型進(jìn)行映射。@Temporal(value=TemporalType.TIME)http://blog.csdn.net/lyq123333321/article/details/44217409
?
@Entity public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id private Long id; private String name; private int age; private String addree; // Getters and Setters }如果沒(méi)有 @javax.persistence.Entity 和 @javax.persistence.Id 這兩個(gè)注解的話(huà),它完全就是一個(gè)典型的 POJO 的 Java 類(lèi),現(xiàn)在加上這兩個(gè)注解之后,就可以作為一個(gè)實(shí)體類(lèi)與數(shù)據(jù)庫(kù)中的表相對(duì)應(yīng)。他在數(shù)據(jù)庫(kù)中的對(duì)應(yīng)的表為:
圖 1. Employee 表對(duì)應(yīng)的 ER 圖
??
映射規(guī)則:
1. 實(shí)體類(lèi)必須用 @javax.persistence.Entity 進(jìn)行注解;
2. 必須使用 @javax.persistence.Id 來(lái)注解一個(gè)主鍵;
3. 實(shí)體類(lèi)必須擁有一個(gè) public 或者 protected 的無(wú)參構(gòu)造函數(shù),之外實(shí)體類(lèi)還可以擁有其他的構(gòu)造函數(shù);
4. 實(shí)體類(lèi)必須是一個(gè)頂級(jí)類(lèi)(top-level class)。一個(gè)枚舉(enum)或者一個(gè)接口(interface)不能被注解為一個(gè)實(shí)體;
5. 實(shí)體類(lèi)不能是 final 類(lèi)型的,也不能有 final 類(lèi)型的方法;
6. 如果實(shí)體類(lèi)的一個(gè)實(shí)例需要用傳值的方式調(diào)用(例如,遠(yuǎn)程調(diào)用),則這個(gè)實(shí)體類(lèi)必須實(shí)現(xiàn)(implements)java.io.Serializable 接口。
將一個(gè) POJO 的 Java 類(lèi)映射成數(shù)據(jù)庫(kù)中的表如此簡(jiǎn)單,這主要得益于 Java EE 5種引入的 Configuration by Exception 的理念,這個(gè)理念的核心就是容器或者供應(yīng)商提供一個(gè)缺省的規(guī)則,在這個(gè)規(guī)則下程序是可以正確運(yùn)行的,如果開(kāi)發(fā)人員有特殊的需求,需要改變這個(gè)默認(rèn)的規(guī)則,那么就是對(duì)默認(rèn)規(guī)則來(lái)說(shuō)就是一個(gè)異常(Exception)。
如上例所示:默認(rèn)的映射規(guī)則就是數(shù)據(jù)庫(kù)表的名字和對(duì)應(yīng)的 Java 類(lèi)的名字相同,表中列的名字和 Java 類(lèi)中相對(duì)應(yīng)的字段的名字相同。
現(xiàn)在我們可以改變這種默認(rèn)的規(guī)則:
清單 2. 使用 @Table 和 @Column 注解修改映射規(guī)則
?
@Entity @Table(name="Workers") public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; @Column(name="emp_name", length=30) private String name; @Column(name="emp_age", nullable=false) private int age; @Column(name="emp_address", nullable=false ,unique=true) private String addree; // Getters and Setters }首先我們可以可以使用
@Javax.persistence.Table 這個(gè)注解來(lái)改變 Java 類(lèi)在數(shù)據(jù)庫(kù)表種對(duì)應(yīng)的表名。這個(gè)注解的定義如下:
@javax.persistence.Column 注解,定義了列的屬性,你可以用這個(gè)注解改變數(shù)據(jù)庫(kù)中表的列名(缺省情況下表對(duì)應(yīng)的列名和類(lèi)的字段名同名);指定列的長(zhǎng)度;或者指定某列是否可以為空,或者是否唯一,或者能否更新或插入。從它的定義可以看出他只可以用在類(lèi)中的方法前面或者字段前面。
其中 name 屬性的值為數(shù)據(jù)庫(kù)中的列名,unique 屬性說(shuō)明該烈是否唯一,nullable 屬性說(shuō)明是否可以為空,length 屬性指明了該列的最大長(zhǎng)度等等。其中 table 屬性將在 @SecondaryTable 的使用中已有過(guò)介紹。
JPA 中兩種注解方式
JPA 中將一個(gè)類(lèi)注解成實(shí)體類(lèi)(entity class)有兩種不同的注解方式:基于屬性(property-based)和基于字段(field-based)的注解。
1,基于字段的注解,就是直接將注解放置在實(shí)體類(lèi)的字段的前面。前面的 Employee 實(shí)體類(lèi)就是使用的這種注解方式;
2,基于屬性的注解,就是直接將注解放置在實(shí)體類(lèi)相應(yīng)的 getter 方法前面,而不是 setter 方法前面(這一點(diǎn)和 Spring 正好相反)。前面的 Employee 實(shí)體類(lèi)如果使用基于屬性注解的方式就可以寫(xiě)成如下形式。
但是同一個(gè)實(shí)體類(lèi)中必須并且只能使用其中一種注解方式,要么是基于屬性的注解,要么是基于字段的注解。兩種不同的注解方式,在數(shù)據(jù)庫(kù)中對(duì)應(yīng)的數(shù)據(jù)庫(kù)表是相同的,沒(méi)有任何區(qū)別,開(kāi)發(fā)人員可以根據(jù)自己的喜好任意選用其中一種注解方式。
@SecondaryTable 的使用
上面介紹的幾個(gè)例子都是一個(gè)實(shí)體類(lèi)映射到數(shù)據(jù)庫(kù)中的一個(gè)表中,那么能否將一個(gè)實(shí)體類(lèi)映射到數(shù)據(jù)庫(kù)兩張或更多表中呢表中呢。在有些情況下如數(shù)據(jù)庫(kù)中已經(jīng)存在原始數(shù)據(jù)類(lèi)型,并且要求不能更改,這個(gè)時(shí)候如果能實(shí)現(xiàn)一個(gè)實(shí)體類(lèi)對(duì)應(yīng)兩張或多張表的話(huà),將是很方便的。JPA2.0 中提供了一個(gè) @SecondaryTablez 注解(annotation)就可以實(shí)現(xiàn)這種情況。下面用一個(gè)例子說(shuō)明一下這個(gè)注解的使用方法:
清單 6. @SecondaryTable 的使用
@Entity @SecondaryTables({ @SecondaryTable(name = "Address"), @SecondaryTable(name = "Comments") }) public class Forum implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; private String username; private String password; @Column(table = "Address", length = 100) private String street; @Column(table = "Address", nullable = false) private String city; @Column(table = "Address") private String conutry; @Column(table = "Comments") private String title; @Column(table = "Comments") private String Comments; @Column(table = "Comments") private Integer comments_length; // Getters and Setters }?
清單 5?中定義了兩個(gè) Secondary 表,分別為 Address 和 Comments,
同時(shí)在 Forum 實(shí)體類(lèi)中也通過(guò) @Column 注解將某些子段分別分配給了這兩張表,那些 table 屬性得值是 Adress 的就會(huì)存在于 Address 表中,
同理 table 屬性的值是 Comments 的就會(huì)存在于 Comments 表中。那些沒(méi)有用 @Column 注解改變屬性默認(rèn)的字段將會(huì)存在于 Forum 表中。
圖 4?就是持久化后在數(shù)據(jù)庫(kù)中對(duì)應(yīng)的表的 ER 圖,從圖中可看出來(lái),這些字段如我們預(yù)料的一樣被映射到了不同的表中。
圖 4. @SecondaryTable 持久化后對(duì)贏得 ER 圖
嵌套映射
在使用嵌套映射的時(shí)候首先要有一個(gè)被嵌套的類(lèi),清單 5?中 Address 實(shí)體類(lèi)使用 @Embeddable 注解,說(shuō)明這個(gè)就是一個(gè)可被嵌套的類(lèi),與 @EmbeddedId 復(fù)合主鍵策略中的主鍵類(lèi)(primary key class)稍有不同的是,這個(gè)被嵌套類(lèi)不用重寫(xiě) hashCode() 和 equals() 方法,復(fù)合主鍵將在后面進(jìn)行介紹。
清單 7. 被嵌套類(lèi)
@Embeddable public class Address implements Serializable { private String street; private String city; private String province; private String country; // Getters and Setters }清單 6 中 Employee 實(shí)體類(lèi)是嵌套類(lèi)的擁有者,其中使用了 @Embedded 注解將 Address 類(lèi)嵌套進(jìn)來(lái)了。
?
清單 8. 嵌套類(lèi)的使用者
?
@Entity public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String email; private String cellPhone; @Embedded private Address address; // Getters and Setters }清單 7?是持久化后生成的數(shù)據(jù)庫(kù)表,可以看出被嵌套類(lèi)的屬性,也被持久化到了數(shù)據(jù)庫(kù)中,默認(rèn)的表名就是嵌套類(lèi)的擁有者的類(lèi)名。
清單 9. 使用嵌套類(lèi)生成的表結(jié)構(gòu)
CREATE TABLE `employee` ( `ID` bigint(20) NOT NULL, `EMAIL` varchar(255) default NULL, `NAME` varchar(255) default NULL, `CELLPHONE` varchar(255) default NULL, `STREET` varchar(255) default NULL, `PROVINCE` varchar(255) default NULL, `CITY` varchar(255) default NULL, `COUNTRY` varchar(255) default NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;被嵌套類(lèi)的注解方式,field 方式或者 property 方式,依賴(lài)于嵌套類(lèi)的擁有者。上面例子中的 Employee 實(shí)體類(lèi)采用的是 field 注解方式,那么在持久化的過(guò)程中,被嵌套類(lèi) Address 也是按照 field 注解方式就行映射的。
我們也可以通過(guò) @Access 注解改變被嵌套類(lèi)映射方式,清單 8?通過(guò)使用 @Access 注解將 Address 被嵌套類(lèi)的注解方式設(shè)定成了 property 方式。清單 9?Employee 仍然采用 filed 注解方式。這種情況下,持久化的時(shí)候,被嵌套類(lèi)就會(huì)按照自己設(shè)定的注解方式映射,而不會(huì)再依賴(lài)于嵌套類(lèi)的擁有者的注解方式。但這并不會(huì)映射的結(jié)果。
清單 10. 基于 property 方式注解的被嵌套類(lèi)
?
@Embeddable @Access(AccessType.PROPERTY) public class Address implements Serializable { private String street; private String city; private String province; private String country; @Column(nullable=false) public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Column(nullable=false,length=50) public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Column(nullable=false,length=20) public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }清單 11. 基于 field 方式注解
@Entity @Access(AccessType. FIELD) public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String email; private String cellPhone; @Embedded private Address address; // Getters and Setters }事先設(shè)定被嵌套類(lèi)的注解方式,是一種應(yīng)該大力提倡的做法,因?yàn)楫?dāng)同一個(gè)類(lèi)被不同的注解方式的類(lèi)嵌套時(shí),可能會(huì)出現(xiàn)一些錯(cuò)誤。
?
總結(jié)
簡(jiǎn)單映射是 ORM,也就是對(duì)象關(guān)系映射中較為簡(jiǎn)單的一種,他只是數(shù)據(jù)庫(kù)表與類(lèi)之間的一一對(duì)應(yīng),并未涉及表之間的關(guān)系,也就未涉及類(lèi)與類(lèi)之間的關(guān)系,也可以說(shuō)是其他如繼承映射,關(guān)聯(lián)關(guān)系映射的基礎(chǔ),所以說(shuō)熟悉并掌握簡(jiǎn)單關(guān)系映射還是很有必要的。
- JSR 3170:JavaTM Persistence API,Version 2.0。 JPA 全稱(chēng) Java Persistence API,JPA 由 EJB 3.0 軟件專(zhuān)家組開(kāi)發(fā),作為 JSR-220 實(shí)現(xiàn)的一部分。但它不囿于 EJB 3.0,你可以在 Web 應(yīng)用、甚至桌面應(yīng)用中使用。JPA 的宗旨是為 POJO 提供持久化標(biāo)準(zhǔn)規(guī)范。
- Hibernate:Java 對(duì)象持久化技術(shù)詳解: Hibernate 是一個(gè)開(kāi)放源代碼的 ORM(對(duì)象關(guān)系映射)框架,它對(duì) JDBC 進(jìn)行了非常輕量級(jí)的對(duì)象封裝,使得 Java 程序員可以隨心所欲的使用對(duì)象編程思維來(lái)操縱數(shù)據(jù)庫(kù)。
- developerWorks Java 技術(shù)專(zhuān)區(qū):這里有數(shù)百篇關(guān)于 Java 編程各個(gè)方面的文章。
討論
- 加入?developerWorks 中文社區(qū):查看開(kāi)發(fā)人員推動(dòng)的博客、論壇、組和維基,并與其他 developerWorks 用戶(hù)交流。
http://www.ibm.com/developerworks/cn/java/j-lo-jpasimpemap/
?
Hibernate中關(guān)于@MappedSuperclass和@Entity的區(qū)別
package com.entity.base;import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass;@MappedSuperclass public class BaseEntity {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Integer id;如果上訴代碼中在使用@MappedSuperclass標(biāo)簽的地方使用了@Entity標(biāo)簽的話(huà),
會(huì)讓hibernate錯(cuò)誤的認(rèn)為所有的Entity都是在一張數(shù)據(jù)表中的。
http://www.voidcn.com/blog/kunshan_shenbin/article/p-4753265.html
?
JPA Java Persistence API,是Java EE 5的標(biāo)準(zhǔn)ORM接口,也是ejb3規(guī)范的一部分。
Hibernate,當(dāng)今很流行的ORM框架,是JPA的一個(gè)實(shí)現(xiàn),但是其功能是JPA的超集。
JPA和Hibernate之間的關(guān)系,可以簡(jiǎn)單的理解為JPA是標(biāo)準(zhǔn)接口,Hibernate是實(shí)現(xiàn)。那么Hibernate是如何實(shí)現(xiàn)與JPA的這種關(guān)系的呢。Hibernate主要是通過(guò)三個(gè)組件來(lái)實(shí)現(xiàn)的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。
hibernate-annotation是Hibernate支持annotation方式配置的基礎(chǔ),它包括了標(biāo)準(zhǔn)的JPA annotation以及Hibernate自身特殊功能的annotation。
hibernate-core是Hibernate的核心實(shí)現(xiàn),提供了Hibernate所有的核心功能。
hibernate-entitymanager實(shí)現(xiàn)了標(biāo)準(zhǔn)的JPA,可以把它看成hibernate-core和JPA之間的適配器,它并不直接提供ORM的功能,而是對(duì)hibernate-core進(jìn)行封裝,使得Hibernate符合JPA的規(guī)范。
Jpa是一種規(guī)范,而Hibernate是它的一種實(shí)現(xiàn)。除了Hibernate,還有EclipseLink(曾經(jīng)的toplink),OpenJPA等可供選擇,所以使用Jpa的一個(gè)好處是,可以更換實(shí)現(xiàn)而不必改動(dòng)太多代碼。
在play中定義Model時(shí),使用的是jpa的annotations,比如javax.persistence.Entity, Table, Column, OneToMany等等。但它們提供的功能基礎(chǔ),有時(shí)候想定義的更細(xì)一些,難免會(huì)用到Hibernate本身的annotation。我當(dāng)時(shí)想,jpa這么弱還要用它干什么,為什么不直接使用hibernate的?反正我又不會(huì)換成別的實(shí)現(xiàn)。
因?yàn)槲液芸鞗Q定不再使用hibernate,這個(gè)問(wèn)題就一直放下了。直到我現(xiàn)在在新公司,做項(xiàng)目要用到Hibernate。
?
我想拋開(kāi)jpa,直接使用hibernate的注解來(lái)定義Model,很快發(fā)現(xiàn)了幾個(gè)問(wèn)題:
我原以為hibernate對(duì)jpa的支持,是另提供了一套專(zhuān)用于jpa的注解,但現(xiàn)在看起來(lái)似乎不是。一些重要的注解如Column, OneToMany等,hibernate沒(méi)有提供,這說(shuō)明jpa的注解已經(jīng)是hibernate的核心,hibernate只提供了一些補(bǔ)充,而不是兩套注解。要是這樣,hibernate對(duì)jpa的支持還真夠足量,我們要使用hibernate注解就必定要使用jpa。
實(shí)際情況是不是這樣?在被群里(Scala交流群132569382)的朋友鄙視一番卻沒(méi)有給出滿(mǎn)意答案的時(shí)候,我又想起了萬(wàn)能的stackoverflow,上去提了兩個(gè)問(wèn):
第一個(gè)是問(wèn)如果想用hibernate注解,是不是一定會(huì)用到j(luò)pa的。網(wǎng)友的回答:“是。如果hibernate認(rèn)為jpa的注解夠用,就直接用。否則會(huì)弄一個(gè)自己的出來(lái)作為補(bǔ)充”
第二個(gè)是問(wèn),jpa和hibernate都提供了Entity,我們應(yīng)該用哪個(gè),還是說(shuō)可以?xún)蓚€(gè)一起用?網(wǎng)友回答說(shuō)“Hibernate的Entity是繼承了jpa的,所以如果覺(jué)得jpa的不夠用,直接使用hibernate的即可”。
http://www.cnblogs.com/chengJAVA/p/3631264.html總結(jié)
以上是生活随笔為你收集整理的hibernate中@Entity和@Table的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PAT、PMT、SDT详解
- 下一篇: FFMPEG系列课程(一)打开视频解码器