Hibernate的註解方法的使用

一、配置映射關係的xml方式

咱們知道,Hibernate是一個典型的ORM框架,用以解決對象和關係的不匹配。其思想就是將關係數據庫中表的記錄映射成爲對象,以對象形式展示,這樣一來,就能夠把對數據庫的操做轉化爲對對象的操做。

而ORM通常是採用xml的格式保存對象與關係數據表的映射,咱們也能夠從下面示例中看到hibernate中的一個映射配置表的表現形式:
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zker.model.job.SysJob" table="SYS_JOB" lazy="true">
        <id name="jobId" column="JOB_ID">
            <generator class="sequence">
                <param name="sequence">SEQ_SYS_JOB</param>
            </generator>
        </id>
        <property name="jobName" type="string" column="JOB_NAME" />
        <property name="jobDesc" type="string" column="JOB_DESC" />
        <property name="lastModity" type="timestamp" column="LAST_MODIFY" />
        <!--與用戶關聯-->
        <set name="sysUsers" table="SYS_USER">
            <key column="JOB_ID" />
            <one-to-many class="com.zker.model.user.SysUser" />
        </set>

    </class>
</hibernate-mapping>

其中對應的實體類和數據庫表結構以下:
public class SysJob {
    /**職位的主鍵ID*/
    private int jobId;

    /**職位的名稱*/
    private String jobName;

    /**職位的描述*/
    private String jobDesc;

    /**職位的修改時間*/
    private Timestamp lastModity;

    /**職位所對應的用戶*/
    private Set<SysUser> sysUsers = new HashSet<SysUser>();

    public int getJobId() {
        return jobId;
    }

    public void setJobId(int jobId) {
        this.jobId = jobId;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobDesc() {
        return jobDesc;
    }

    public void setJobDesc(String jobDesc) {
        this.jobDesc = jobDesc;
    }

    public Timestamp getLastModity() {
        return lastModity;
    }

    public void setLastModity(Timestamp lastModity) {
        this.lastModity = lastModity;
    }

    public Set<SysUser> getSysUsers() {
        return sysUsers;
    }

    public void setSysUsers(Set<SysUser> sysUsers) {
        this.sysUsers = sysUsers;
    }
}
 

二、註解的優勢


而完成這個ORM映射關係配置的方式,還有一種,就是使用註解。
  • 充分利用 Java 的反射機制獲取類結構信息,這些信息能夠有效減小配置的工做
  • 註釋和 Java 代碼位於一個文件中,有助於加強程序的內聚性,便於程序員開發

咱們能夠看以下的一個示例來感覺這種形式:

@Entity
@Table(name = "t_student")
@Domain(name = "學生")
@Generated
@DataIdentify(identifies = "number")
public class Student extends BaseDomain<Student> implements Addable, Modifiable<Student>, Deletable {
	private String name;
	private String number;
	private Sex sex;

	@Basic
	@NotSemanticNull(groups = {Groups.Add.class, Groups.Update.class})
	@Property(name = "姓名")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

        ...

}


三、經常使用註解的使用方法

3.1 類級別的註解

  • @Entity     映射實體類
  • @Table      映射數句庫表

@Entity(name = "tableName") - 必須,註解將一個類聲明爲一個實體bean,即指出該Java 類爲實體類,將映射到指定的數據庫表
  • 屬性:
  • name - 可選,對應數據庫中的一個表。若表名與實體類名相同,則能夠省略

@Table(name = "", catalog = "", schema = "")  - 可選,一般和@Entity 配合使用,只能標註在實體的 class 定義處,表示實體對應的數據庫表的信息
  • 屬性:
  • name - 可選,表示表的名稱,默認的表名和實體名稱一致,只有在不一致的狀況下才須要指定表名
  • catalog - 可選,表示Catalog 名稱,默認爲 Catalog("")
  • schema - 可選 , 表示 Schema 名稱 , 默認爲Schema("")

3.2 屬性級別的註解

  • @Id                                 映射生成主鍵
  • @GeneratedValue         定義主鍵生成策略
  • @SequenceGenerator  聲明瞭一個數據庫序列
  • @Version                       定義樂觀鎖
  • @Basic                           聲明屬性的存取策略
  • @Column                       映射表的列
  • @Transient                    定義暫態屬性

屬性級別的註解,都是放在其對應的getter前。

3.2.1 與主鍵相關注解

@Id - 必須,定義了映射到數據庫表的主鍵的屬性,一個實體只能有一個屬性被映射爲主鍵,置於 getXxx() 前

@GeneratedValue(strategy = GenerationType , generator="") - 可選,用於定義主鍵生成策略
  • 屬性:
  • 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使用
  • generator - 表示主鍵生成器的名稱,這個屬性一般和ORM框架相關 , 例如:Hibernate 能夠指定 uuid 等主鍵生成方式

@SequenceGenerator — 註解聲明瞭一個數據庫序列
  • 屬性:
  • name - 表示該表主鍵生成策略名稱,它被引用在@GeneratedValue中設置的「gernerator」值中
  • sequenceName - 表示生成策略用到的數據庫序列名稱
  • initialValue - 表示主鍵初始值,默認爲0
  • allocationSize - 每次主鍵值增長的大小,例如設置成1,則表示每次建立新記錄後自動加1,默認爲50


3.2.2 與非主鍵相關注解

@Version - 能夠在實體bean中使用@Version註解,經過這種方式可添加對樂觀鎖定的支持(見參考連接)

@Basic - 用於聲明屬性的存取策略:
  • @Basic(fetch=FetchType.EAGER)   即時獲取(默認的存取策略)
  • @Basic(fetch=FetchType.LAZY)       延遲獲取

@Column - 可將屬性映射到列,使用該註解來覆蓋默認值,@Column描述了數據庫表中該字段的詳細定義
  • 屬性:
  • name - 可選,表示數據庫表中該字段的名稱,默認情形屬性名稱一致
  • nullable - 可選,表示該字段是否容許爲 null,默認爲 true
  • unique - 可選,表示該字段是不是惟一標識,默認爲 false
  • length - 可選,表示該字段的大小,僅對 String 類型的字段有效,默認值255
  • insertable - 可選,表示在ORM框架執行插入操做時,該字段是否應出現INSETRT語句中,默認爲 true
  • updateable - 可選,表示在ORM 框架執行更新操做時,該字段是否應該出如今UPDATE 語句中,默認爲 true。對於一經建立就不能夠更改的字段,該屬性很是有用,如對於 birthday 字段
  • columnDefinition - 可選,表示該字段在數據庫中的實際類型。一般ORM 框架能夠根據屬性類型自動判斷數據庫中字段的類型,可是對於Date 類型仍沒法肯定數據庫中字段類型到底是 DATE,TIME 仍是 TIMESTAMP. 此外 ,String 的默認映射類型爲 VARCHAR, 若是要將 String 類型映射到特定數據庫的 BLOB或 TEXT 字段類型,該屬性很是有用

@Transient - 可選,表示該屬性並不是一個到數據庫表的字段的映射,ORM框架將忽略該屬性,若是一個屬性並不是數據庫表的字段映射,就務必將其標示爲@Transient,不然ORM框架默認其註解爲 @Basic


3.3 映射實體類的關聯關係

單向一對多:一方有集合屬性,包含多個多方,而多方沒有一方的引用。 用戶--->電子郵件
單向多對一:多方有一方的引用,一方沒有多方的引用。 論文類別---> 類別
雙向一對多:兩邊都有多方的引用,方便查詢。 班級---> 學生
雙向多對一:兩邊都有多方的引用,方便查詢。
單向多對多:須要一箇中間表來維護兩個實體表。 論壇--->文章
單向一對一:數據惟一,數據庫數據也是一對一。 艦船---> 水手
主鍵相同的一對一:使用同一個主鍵,省掉外鍵關聯。 客戶---> 地址

3.3.1 關聯映射的一些共有屬性

@JoinColumn - 可選,用於描述一個關聯的字段。 @JoinColumn和@Column相似,介量描述的不是一個簡單字段,而是一個關聯字段,例如描述一個 @ManyToOne 的字段。(即用來 定義外鍵在咱們這個表中的屬性名,例如實體Order有一個User user屬性來關聯實體User,則Order的user屬性爲一個外鍵
  • 屬性:
  • name - 該字段的名稱,因爲@JoinColumn描述的是一個關聯字段,如ManyToOne, 則默認的名稱由其關聯的實體決定

@OneToOne@OneToMany@ManyToOneManyToMany 的共有屬性:
  • fetch - 配置加載方式。取值有:
    • Fetch.EAGER -  及時加載,多對一默認是Fetch.EAGER 
    • Fetch.LAZY - 延遲加載,一對多默認是Fetch.LAZY
  • cascade - 設置級聯方式,取值有:
    • CascadeType.PERSIST - 保存  - 調用JPA規範中的persist(),不適用於Hibernate的save()方法
    • CascadeType.REMOVE - 刪除  - 調用JPA規範中的remove()時,適用於Hibernate的delete()方法
    • CascadeType.MERGE - 修改  - 調用JPA規範中merge()時,不適用於Hibernate的update()方法 
    • CascadeType.REFRESH - 刷新  - 調用JPA規範中的refresh()時,適用於Hibernate的flush()方法
    • CascadeType.ALL - 所有  - JPA規範中的全部持久化方法
  • targetEntity - 配置集合屬性類型,如:@OneToMany(targetEntity=Book.class)

@OneToOne – 表示一個一對一的映射
主表類A與從表類B的主鍵值相對應
主表:
@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
public B getB(){
  return b;
}

從表:無
主表A中有一個從表屬性是B類型的b
主表:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="主表外鍵")   //這裏指定的是數據庫中的外鍵字段。
public B getB(){
  return b;
}

從表:無
主表A中有一個從表屬性是B類型的b,同時,從表B中有一個主表屬性是A類型的a
主表:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="主表外鍵")   //這裏指定的是數據庫中的外鍵字段。
public B getB(){
  return b;
}

從表:
@OneToOne(mappedBy = "主表類中的從表屬性")
public 主表類 get主表類(){
  return 主表對象
}

@ManyToOne - 表示一個多對一的映射,該註解標註的屬性一般是數據庫表的外鍵
單向多對一:多方有一方的引用,一方沒有多方的引用
在多方
@ManyToOne(targetEntity=XXXX.class)   //指定關聯對象
@JoinColumn(name="")                 //指定產生的外鍵字段名
雙向多對一:配置方式同雙向一對多
// 示例
// 訂單 Order 和用戶 User 是一個 ManyToOne 的關係
// 在 Order 類中定義
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
  return user;
}

@OneToMany - 描述一個一對多的關聯,該屬性應該爲集合類型,在數據庫中並無實際字段
單向一對多:一方有集合屬性,包含多個多方,而多方沒有一方的引用
@OneToMany  默認會使用鏈接表作一對多關聯
添加@JoinColumn(name="xxx_id") 後,就會使用外鍵關聯,而不使用鏈接表了
雙向一對多:
1)在多方
@ManyToOne
@JoinColumn(name="本身的數據庫外鍵列名")
 
2)在一方
@OneToMany(mappedBy="多端的關聯屬性名") //mappedBy至關於inverse,維護外鍵的控制權,不能和JoinColumn同時使用
@JoinColumn(name="對方的數據庫外鍵列名")
注意:對於外鍵的維護,若是是雙向一對多,但願雙方都可以維護外鍵,則不能使用mappedBy,而應該雙方都使用@JoinColumn

@ManyToMany - 可選,描述一個多對多的關聯
  • 屬性:
  • targetEntity - 表示多對多關聯的另外一個實體類的全名,例如:package.Book.class
  • mappedBy - 用在雙向關聯中,把關係的維護權翻轉。    
單向多對多關聯:
在主控方加入@ManyToMany註解便可。
雙向多對多關聯:
兩個實體間互相關聯的屬性必須標記爲@ManyToMany,並相互指定targetEntity屬性。
有且只有一個實體的@ManyToMany註解須要指定mappedBy屬性,指向targetEntity的集合屬性名稱。

3.3.2 關聯映射的其餘補充

@JoinTable其實同時也是配合 @ManyToMany使用的, @ManyToMany註釋表示該對象是多對多關係的一端,而後利用@JoinTable來定義關聯關係(利用中間表來創建聯繫, 緣由戳這裏),其中name屬性指定中間表名稱,j oinColumns定義中間表與該表的外鍵關係,inverseJoinColumns屬性定義了中間表與另一端的外鍵關係。

@JoinTable - 定義關聯表, 該關聯表包含了指回實體表的外鍵(經過@JoinTable.joinColumns) 以及指向目標實體表的外鍵(經過@JoinTable.inverseJoinColumns)

e.g.
以下表示:該屬性對應字段爲"resource_type",該字段實際在另一張名"r_role_x_resource_type"表中,與該表("p_role")經過"role_id"進行外鍵連接

(class Role --> table "p_role")
@ElementCollection
@JoinTable(name = "r_role_x_resource_type", joinColumns = @JoinColumn(name = "role_id"))
@Column(name = "resource_type")
@JSONField(serialize = false)
@Cache(usage = CacheConcurrencyStrategy.NONE)
public List<Class<? extends Resourceable>> getResourceTypeList() {
	return resourceTypeList;
}

e.g.
以下表示:關聯的表爲「r_role_x_permission",其中關聯外鍵爲"role_id",該表又經過"permission_id"連接第三張表,即目標實體表

(class Role --> table "p_role")
@ManyToMany
@JoinTable(name = "r_role_x_permission", joinColumns = @JoinColumn(name = "role_id"),
	inverseJoinColumns = @JoinColumn(name = "permission_id"))
public List<Permission> getPermissionList() {
	return permissionList;
}



四、其餘註解

@DiscriminatorValue - 一張表對應一整棵類繼承樹時,該類別對應的「表part」

首先參考這篇文章,很重要: hibernate映射繼承關係(一):一張表對應一整棵類繼承樹,從文中能夠知道,用一個表來存儲對應的整個類別的數據,好比有Cat和Animal,Cat是Animal的子類,我僅用Animal一個表來存儲Animal和Cat的字段和數據,而不是分紅兩個表。那麼當我進行映射關係的時候,假如我要Cat類映射到Animal中Cat的部分,如何處理?在Animal中定義一個字段用來區分不一樣的表,好比Animal表中我額外增長字段名爲Type,那麼在Animal這一張表中,咱們本屬於Animal表內容的,該字段咱們設置爲animal,本屬於Cat表的,該字段咱們設置爲cat。你能夠理解爲,新增長字段來用以在同一個表中區分不一樣類別的內容。

因此對應在註解上的使用的一個映射關係表示,就是這樣的:對於」父類「,即準備用來囊括全部內容的那個表,咱們須要定義這個對應的類爲 @DiscriminatorColumn(name = "xxx", discriminatorType = DiscriminatorType.xxx) ,這裏的 name就是指定表中用來區別各種內容的字段 ,而對於」子類「,咱們須要註解標明@DiscriminatorValue(xxx),這裏的xxx即對應了父類中的 「區別用字段」 裏的標識。

舉例來講,就是假如咱們但願將Animal和Cat的內容都只存儲在Animal這張表裏,那麼爲了區份內容,咱們對於Animal這個表新增某字段如 type;Animal的類,註解爲@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING) ,同時設置@DiscriminatorValue("animal");Cat extends Animal,Cat的類,註解爲@DiscriminatorValue(「cat");那麼Animal這個表中,字段type中,爲animal的元組映射Animal類,爲cat的元組映射Cat類。

而這種方式,多用於數據庫字典概念。

@Transient
若是某個屬性不須要被持久化,能夠加上 @javax.persistence.Transient 註解或者使用 java 的 transient 關鍵字。

@Lob
實體BLOB、CLOB類型的註解:
  • BLOB類型屬性聲明爲byte[]或者java.sql.Blob,多用來直接將文件存儲在數據庫字段中(如圖片);
  • CLOB類型的屬性聲明爲String或java.sql.Clob (詳可見參考連接中《Hibernate的Annotation實體BLOB、CLOB類型註解》)


五、參考連接

相關文章
相關標籤/搜索