hibernate中@Entity和@Table的區別


Java Persistence API定義了一種定義,可以將常規的普通Java對象(有時被稱作POJO)映射到數據庫。
這些普通Java對象被稱作Entity Bean。
除了是用Java Persistence元數據將其映射到數據庫外,Entity Bean與其他Java類沒有任何區別。
事實上,創建一個Entity Bean對象相當於新建一條記錄,刪除一個Entity Bean會同時從數據庫中刪除對應記錄,修改一個Entity Bean時,容器會自動將Entity Bean的狀態和數據庫同步。

Java Persistence API還定義了一種查詢語言(JPQL),具有與SQL相類似的特征,只不過做了裁減,以便處理Java對象而非原始的關系表。



 hibernate中@Entity和@Table的區別:
@Entity說明這個class是實體類,並且使用默認的orm規則,即class名即數據庫表中表名,class字段名即表中的字段名
如果想改變這種默認的orm規則,就要使用@Table來改變class名與數據庫中表名的映射規則,@Column來改變class中字段名與db中表的字段名的映射規則

 

@Entity注釋指名這是一個實體Bean,@Table注釋指定了Entity所要映射帶數據庫表,其中@Table.name()用來指定映射表的表名。
如果缺省@Table注釋,系統默認采用類名作為映射表的表名。實體Bean的每個實例代表數據表中的一行數據,行中的一列對應實例中的一個屬性。

@Column注釋定義了將成員屬性映射到關系表中的哪一列和該列的結構信息,屬性如下:
1)name:映射的列名。如:映射tbl_user表的name列,可以在name屬性的上面或getName方法上面加入;
2)unique:是否唯一;
3)nullable:是否允許為空;
4)length:對於字符型列,length屬性指定列的最大字符長度;
5)insertable:是否允許插入;
6)updatetable:是否允許更新;
7)columnDefinition:定義建表時創建此列的DDL;
8)secondaryTable:從表名。如果此列不建在主表上(默認是主表),該屬性定義該列所在從表的名字。
@Id注釋指定表的主鍵,它可以有多種生成方式:

1)TABLE:容器指定用底層的數據表確保唯一;
2)SEQUENCE:使用數據庫德SEQUENCE列萊保證唯一(Oracle數據庫通過序列來生成唯一ID);
3)IDENTITY:使用數據庫的IDENTITY列萊保證唯一;
4)AUTO:由容器挑選一個合適的方式來保證唯一;
5)NONE:容器不負責主鍵的生成,由程序來完成。

@GeneratedValue注釋定義了標識字段生成方式。

@Temporal注釋用來指定java.util.Date或java.util.Calender屬性與數據庫類型date、time或timestamp中的那一種類型進行映射。

@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 
 }

如果沒有 @javax.persistence.Entity 和 @javax.persistence.Id 這兩個注解的話,它完全就是一個典型的 POJO 的 Java 類,現在加上這兩個注解之后,就可以作為一個實體類與數據庫中的表相對應。他在數據庫中的對應的表為:

圖 1. Employee 表對應的 ER 圖

  

映射規則:

1. 實體類必須用 @javax.persistence.Entity 進行注解;

2. 必須使用 @javax.persistence.Id 來注解一個主鍵;

3. 實體類必須擁有一個 public 或者 protected無參構造函數,之外實體類還可以擁有其他的構造函數;

4. 實體類必須是一個頂級類(top-level class)。一個枚舉(enum)或者一個接口(interface)不能被注解為一個實體;

5. 實體不能是 final 類型的,也不能有 final 類型的方法;

6. 如果實體類的一個實例需要用傳值的方式調用(例如,遠程調用),則這個實體類必須實現(implements)java.io.Serializable 接口。

將一個 POJO 的 Java 類映射成數據庫中的表如此簡單,這主要得益於 Java EE 5種引入的  Configuration by Exception 的理念,這個理念的核心就是容器或者供應商提供一個缺省的規則,在這個規則下程序是可以正確運行的,如果開發人員有特殊的需求,需要改變這個默認的規則,那么就是對默認規則來說就是一個異常(Exception)。

如上例所示:默認的映射規則就是數據庫表的名字和對應的 Java 類的名字相同,表中列的名字和 Java 類中相對應的字段的名字相同。

現在我們可以改變這種默認的規則:

清單 2. 使用 @Table 和 @Column 注解修改映射規則

 

 @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 這個注解來改變 Java 類在數據庫表種對應的表名。這個注解的定義如下:

@javax.persistence.Column 注解,定義了列的屬性,你可以用這個注解改變數據庫中表的列名(缺省情況下表對應的列名和類的字段名同名);指定列的長度;或者指定某列是否可以為空,或者是否唯一,或者能否更新或插入。

從它的定義可以看出他只可以用在類中的方法前面或者字段前面。

其中 name 屬性的值為數據庫中的列名,unique 屬性說明該烈是否唯一,nullable 屬性說明是否可以為空,length 屬性指明了該列的最大長度等等。其中 table 屬性將在 @SecondaryTable 的使用中已有過介紹。

JPA 中兩種注解方式

JPA 中將一個類注解成實體類(entity class)有兩種不同的注解方式:基於屬性(property-based)和基於字段(field-based)的注解。

1,基於字段的注解,就是直接將注解放置在實體類的字段的前面。前面的 Employee 實體類就是使用的這種注解方式;

2,基於屬性的注解,就是直接將注解放置在實體類相應的 getter 方法前面,而不是 setter 方法前面(這一點和 Spring 正好相反)。前面的 Employee 實體類如果使用基於屬性注解的方式就可以寫成如下形式。

但是同一個實體類中必須並且只能使用其中一種注解方式,要么是基於屬性的注解,要么是基於字段的注解。兩種不同的注解方式,在數據庫中對應的數據庫表是相同的,沒有任何區別,開發人員可以根據自己的喜好任意選用其中一種注解方式。

@SecondaryTable 的使用

上面介紹的幾個例子都是一個實體類映射到數據庫中的一個表中,那么能否將一個實體類映射到數據庫兩張或更多表中呢表中呢。在有些情況下如數據庫中已經存在原始數據類型,並且要求不能更改,這個時候如果能實現一個實體類對應兩張或多張表的話,將是很方便的。JPA2.0 中提供了一個 @SecondaryTablez 注解(annotation)就可以實現這種情況。下面用一個例子說明一下這個注解的使用方法:

清單 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 中定義了兩個 Secondary 表,分別為 Address 和 Comments,
同時在 Forum 實體類中也通過 @Column 注解將某些子段分別分配給了這兩張表,那些 table 屬性得值是 Adress 的就會存在於 Address 表中,
同理 table 屬性的值是 Comments 的就會存在於 Comments 表中。那些沒有用 @Column 注解改變屬性默認的字段將會存在於 Forum 表中。

圖 4 就是持久化后在數據庫中對應的表的 ER 圖,從圖中可看出來,這些字段如我們預料的一樣被映射到了不同的表中。

圖 4. @SecondaryTable 持久化后對贏得 ER 圖

嵌套映射

在使用嵌套映射的時候首先要有一個被嵌套的類,清單 5 中 Address 實體類使用 @Embeddable 注解,說明這個就是一個可被嵌套的類,與 @EmbeddedId 復合主鍵策略中的主鍵類(primary key class)稍有不同的是,這個被嵌套類不用重寫 hashCode() 和 equals() 方法,復合主鍵將在后面進行介紹。

清單 7. 被嵌套類
 @Embeddable 
 public class Address implements Serializable  { 

    private String street; 
    private String city; 
    private String province; 
    private String country; 

    // Getters and Setters 

 }

清單 6 中 Employee 實體類是嵌套類的擁有者,其中使用了 @Embedded 注解將 Address 類嵌套進來了。

 

清單 8. 嵌套類的使用者

 

 @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 是持久化后生成的數據庫表,可以看出被嵌套類的屬性,也被持久化到了數據庫中,默認的表名就是嵌套類的擁有者的類名。

清單 9. 使用嵌套類生成的表結構
 
 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;

被嵌套類的注解方式,field 方式或者 property 方式,依賴於嵌套類的擁有者。上面例子中的 Employee 實體類采用的是 field 注解方式,那么在持久化的過程中,被嵌套類 Address 也是按照 field 注解方式就行映射的。

我們也可以通過 @Access 注解改變被嵌套類映射方式,清單 8 通過使用 @Access 注解將 Address 被嵌套類的注解方式設定成了 property 方式。清單 9 Employee 仍然采用 filed 注解方式。這種情況下,持久化的時候,被嵌套類就會按照自己設定的注解方式映射,而不會再依賴於嵌套類的擁有者的注解方式。但這並不會映射的結果。

清單 10. 基於 property 方式注解的被嵌套類

 

 @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 
   }

事先設定被嵌套類的注解方式,是一種應該大力提倡的做法,因為當同一個類被不同的注解方式的類嵌套時,可能會出現一些錯誤。

 

總結

簡單映射是 ORM,也就是對象關系映射中較為簡單的一種,他只是數據庫表與類之間的一一對應,並未涉及表之間的關系,也就未涉及類與類之間的關系,也可以說是其他如繼承映射,關聯關系映射的基礎,所以說熟悉並掌握簡單關系映射還是很有必要的。

  • JSR 3170:JavaTM Persistence API,Version 2.0。 JPA 全稱 Java Persistence API,JPA 由 EJB 3.0 軟件專家組開發,作為 JSR-220 實現的一部分。但它不囿於 EJB 3.0,你可以在 Web 應用、甚至桌面應用中使用。JPA 的宗旨是為 POJO 提供持久化標准規范。
  • Hibernate:Java 對象持久化技術詳解: Hibernate 是一個開放源代碼的 ORM(對象關系映射)框架,它對 JDBC 進行了非常輕量級的對象封裝,使得 Java 程序員可以隨心所欲的使用對象編程思維來操縱數據庫。
  • developerWorks Java 技術專區:這里有數百篇關於 Java 編程各個方面的文章。

討論

  • 加入 developerWorks 中文社區:查看開發人員推動的博客、論壇、組和維基,並與其他 developerWorks 用戶交流。

http://www.ibm.com/developerworks/cn/java/j-lo-jpasimpemap/

 

Hibernate中關於@MappedSuperclass和@Entity的區別

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標簽的地方使用了@Entity標簽的話,

會讓hibernate錯誤的認為所有的Entity都是在一張數據表中的。

http://www.voidcn.com/blog/kunshan_shenbin/article/p-4753265.html

 

JPA Java Persistence API,是Java EE 5的標准ORM接口,也是ejb3規范的一部分。

Hibernate,當今很流行的ORM框架,是JPA的一個實現,但是其功能是JPA的超集。

JPA和Hibernate之間的關系,可以簡單的理解為JPA是標准接口,Hibernate是實現。那么Hibernate是如何實現與JPA的這種關系的呢。Hibernate主要是通過三個組件來實現的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。

hibernate-annotation是Hibernate支持annotation方式配置的基礎,它包括了標准的JPA annotation以及Hibernate自身特殊功能的annotation。

hibernate-core是Hibernate的核心實現,提供了Hibernate所有的核心功能。

hibernate-entitymanager實現了標准的JPA,可以把它看成hibernate-core和JPA之間的適配器,它並不直接提供ORM的功能,而是對hibernate-core進行封裝,使得Hibernate符合JPA的規范。

Jpa是一種規范,而Hibernate是它的一種實現。除了Hibernate,還有EclipseLink(曾經的toplink),OpenJPA等可供選擇,所以使用Jpa的一個好處是,可以更換實現而不必改動太多代碼。

在play中定義Model時,使用的是jpa的annotations,比如javax.persistence.Entity, Table, Column, OneToMany等等。但它們提供的功能基礎,有時候想定義的更細一些,難免會用到Hibernate本身的annotation。我當時想,jpa這么弱還要用它干什么,為什么不直接使用hibernate的?反正我又不會換成別的實現。

因為我很快決定不再使用hibernate,這個問題就一直放下了。直到我現在在新公司,做項目要用到Hibernate。

 

我想拋開jpa,直接使用hibernate的注解來定義Model,很快發現了幾個問題:

  1. jpa中有Entity, Table,hibernate中也有,但是內容不同
  2. jpa中有Column,OneToMany等,Hibernate中沒有,也沒有替代品

我原以為hibernate對jpa的支持,是另提供了一套專用於jpa的注解,但現在看起來似乎不是。一些重要的注解如Column, OneToMany等,hibernate沒有提供,這說明jpa的注解已經是hibernate的核心,hibernate只提供了一些補充,而不是兩套注解。要是這樣,hibernate對jpa的支持還真夠足量,我們要使用hibernate注解就必定要使用jpa。

實際情況是不是這樣?在被群里(Scala交流群132569382)的朋友鄙視一番卻沒有給出滿意答案的時候,我又想起了萬能的stackoverflow,上去提了兩個問:

  1. http://stackoverflow.com/questions/8306742/if-i-want-to-use-hibernate-with-annotation-do-i-have-to-use-javax-persistence
  2. http://stackoverflow.com/questions/8306793/why-jpa-and-hibernate-both-have-entity-and-table-annotations

第一個是問如果想用hibernate注解,是不是一定會用到jpa的。網友的回答:“是。如果hibernate認為jpa的注解夠用,就直接用。否則會弄一個自己的出來作為補充”

第二個是問,jpa和hibernate都提供了Entity,我們應該用哪個,還是說可以兩個一起用?網友回答說“Hibernate的Entity是繼承了jpa的,所以如果覺得jpa的不夠用,直接使用hibernate的即可”。

 http://www.cnblogs.com/chengJAVA/p/3631264.html
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM