Hibernate 5.3(四) [補充中.........]
前言
本篇文章主要講解有關Hibernate的註解,由於時間有限,我只能講解一些比較常用,還有一些,如果以後用到,會陸續補充進來的。
題外知識
說時間JPA 、EJB 這些都是啥呀,經常看到有些人掛在嘴邊。
- JPA: Java 持久層的API,主要為我們提供了ORM物件的處理。Hibernate 就是在這個基礎上編寫的。
- EJB:是以前一個老的,裡面的實體Bean,已經逐漸被JPA替代,JPA的使用範圍更廣。
javax persistence or org hibernate annotations
相信使用過Hibernate 註解,自動提示的時候,會出現這兩種註解,那麼我們該使用哪種呢,看了上面的介紹,你應該瞭解實際上,Hibernate是基於JPA,org hibernate annotations 實際上在原先的註解上進行的修改成自己,但是我們使用的話一般還是使用javax persistence 的多,本文的介紹也是基於這個。
Hibernate 註解文件哪裡找
如果你使用的是Hibernate 註解,那麼開啟你當時下載的Hibernate的資料,裡面有一個D:\hibernate\hibernate-release-5.3.0.Beta1\documentation\javadocs\org\hibernate\annotations(自己對應去找)
如果是使用的javax persistence 註解,那就直接找到javaee 的api 文件,即可看到。
註解放在欄位ORget方法
在對一個類進行註解時,你可以選擇對它的的屬性或者方法進行註解,根據你的選擇,Hibernate的訪問型別分別為 field或property. EJ3規範要求在需要訪問的元素上進行註解宣告,例如,如果訪問型別為 property就要在getter方法上進行註解宣告, 如果訪問型別為 field就要在欄位上進行註解宣告.應該儘量避免混合使用這兩種訪問型別. Hibernate根據@Id 或 @EmbeddedId的位置來判斷訪問型別。
Tip
本次部落格,由於很多註解,只是起演示作用,沒有太多實用意思,還有就是註解我都寫在一起,有些重複的,我註釋,沒有分開,這需要讀者,需要在看的時候,有自己的思考,不要看的一臉懵。
例子與講解
import java.io.File;
import java.util.Date;
import javax.persistence.*;
//@IdClass(ArtitleId.class)
@Entity
@Table(name="ARTITLE")
public class Artitle {
// @Id
// private Integer titleid;
// @Id
// private Integer contentid;
@Id
@TableGenerator(name="mytablegenerator",table="generator_table",allocationSize=1,initialValue=1,
pkColumnName="generatorid",pkColumnValue="user_id",valueColumnName="generatorid_value")
@GeneratedValue(strategy=GenerationType.TABLE,generator="mytablegenerator")
@Column
private int title_id;
/*@EmbeddedId
private ArtitleId artitleid;//複合物件(元件)作為主鍵
*/ @Column
private String title;
@Column
@Basic(fetch=FetchType.LAZY,optional=true)
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column
private Date createdate;
@Enumerated(value=EnumType.ORDINAL)
@Column
private Status status;
@Lob
private File file;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="first", [email protected](nullable=false)),
@AttributeOverride(name="last",[email protected](nullable=false)),
})
private Name name;
//為了減少程式碼量,所有屬性的set、get方法全部省略,自己填充。
}
/*@table 用來指定註解實體對應的表,這裡的name是可選,如果你不指定,
* 那麼資料庫的表名,就是你自己的實體類名。該註解中有一個屬性uniqueConstraints,因為一個表
* 可以有多個唯一約束,可以通過@UniqueConstraint ,來指定每一個唯一約束由哪些欄位組成。
* [email protected](columnNames={"",""}),這裡列名,就是你欄位對應的@column的name
*
*@Transient 用來指定某個欄位不需要持久化
*
*@Temporal 用來對映欄位型別java.util.Date and java.util.Calendar,其他型別不可以指定該註解
*
*@Id 用於指定某一個欄位對映成主鍵
*
*@GeneratedValue 這個註解 用來指定主鍵生成策略:有下面四種
*GenerationType.TABLE 使用一個特定的資料庫表格來儲存主鍵,持久化引擎通過關係資料庫的一張特定的表格來生成主鍵。
*該策略一般與另外一個註解一起使用@TableGenerator,@TableGenerator註解指定了生成主鍵的表(可以在實體類上指定也可
*以在主鍵欄位或屬性上指定),然後JPA將會根據註解內容自動生成一張表作為序列表(或使用現有的序列表)。如果不指定序列表,
*則會生成一張預設的序列表,表中的列名也是自動生成
*GenerationType.SEQUENCE 在某些資料庫中,不支援主鍵自增長,比如Oracle,其提供了一種叫做"序列(sequence)"的機制生成主鍵。此時,GenerationType.SEQUENCE就可以作為主鍵生成策略。
*GenerationType.IDENTITY 此種主鍵生成策略就是通常所說的主鍵自增長,資料庫在插入資料時,會自動給主鍵賦值,比如MYSQL可以在建立表時宣告"auto_increment" 來指定主鍵自增長
*GenerationType.AUTO 把主鍵生成策略交給持久化引擎(persistence engine),持久化引擎會根據資料庫在以上三種主鍵生成策略中選擇其中一種。
*該註解有一個屬性generator 是用來指定主鍵生成的東東,SequenceGenerator or TableGenerator 屬性的值,就是這些生產者name的字串。
*
*@TableGenerator 之前在講解主鍵生成的,有一種是通過資料庫表格,就是該註解去處理。裡面有的屬性即使用參看下圖:
![在這裡插入圖片描述](https://img-blog.csdn.net/20180919192712282?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZlbnVzMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
![在這裡插入圖片描述](https://img-blog.csdn.net/20180919192739860?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZlbnVzMzIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
生成器的表中只會有一個數據,這個資料的值會根據你的設定,每次自增的。
*@SequenceGenerator 和@TableGenerator 很類似,就是它是針對oracle的主鍵的序列
*
*
*@Entity 主要標識該類為實體類,裡面有一個name,使用該註解,在hql可以識別。**這個每一個實體類還必須要新增該註解,否則,Hibernate找不到。**,並不是所有的都要改註解,在一些元件類,是不需要,該註解只是針對實體類。
*
*@Basic 主要是用於欄位和column的基本對映,fetch 主要設定是否懶載入(Hibernate在
*建立一個實體Bean的例項時,不會即時將這個屬性的值從資料庫中讀出. 只有在該實體Bean的
*這個屬性第一次被呼叫時,Hibernate才會去獲取對應的值),optional 欄位是否可以為空
*
*@Enumerated 指定某個欄位持久化成列舉型別 ,你需要自己先定義列舉類,value 用於指定該欄位的列舉值
*
*@Lob 將資料庫欄位對映成大的物件型別,大文字型別名稱為clob,大二進位制型別名稱為blob。該註解既可以
*對映對映二進位制,也可以對映字元,看你欄位的型別。(常用某個描述、自我介紹、檔案、圖片)
*
*@Column 將欄位和列對應 。常用屬性:
name 可選,列名(預設值是屬性名)
unique 可選,是否在該列上設定唯一約束(預設值false)
nullable 可選,是否設定該列的值可以為空(預設值false)
insertable 可選,該列是否作為生成的insert語句中的一個列(預設值true)
updatable 可選,該列是否作為生成的update語句中的一個列(預設值true)
columnDefinition 可選: 為這個特定列覆蓋SQL DDL片段 (這可能導致無法在不同資料庫間移植)
table 可選,定義對應的表(預設為主表)
length 可選,列長度(預設值255)
precision 可選,列十進位制精度(decimal precision)(預設值0)
scale 可選,如果列十進位制數值範圍(decimal scale)可用,在此設定(預設值0)
*
*@Embedded 這個註解用於元件欄位的對映,需要為這個元件類新增@Embeddable ,元件類需要實現序列化介面,你記住,物件儲存到資料庫,不能序列化,你搞個毛毛,String等型別都已經在內部實現了,所以才不要你顯式的申明,同時我不太建議在組建類在欄位去@Column 去設定,因為一般都會在持久化類中使用@AttributeOverrides 去覆蓋,去設定元件屬性的Column。
@AttributeOverrides({
@AttributeOverride(name="first",[email protected](nullable=false)),
@AttributeOverride(name="last",[email protected](nullable=false)),
})
private Name name;
*@AttributeOverrides 這個是屬性重寫,對於一個表有元件,hibernate是將物件的各個欄位,
*新增新增到這個表,你就可以通過這個屬性去覆蓋原來元件類的欄位的設定,如果沒有,就是預設用
*元件類的對映關係。這裡的name,就是你元件類對應的欄位名
*
*在使用該註解,可能會出現元件類的屬性還是元件類,出現多重的巢狀。
*你可以通過當前元件屬性名.元件類的欄位名,去設定。
*
*@EmbeddedId 該註解主要是用於主鍵是複合物件,使用該註解就不可以在使用@id。可以配合
*@AttributeOverrides 去重寫複合屬性的欄位。
*
*上面使用@EmbeddedId 可以註解主鍵是複合物件,還可以通過@IdClass(ArtitleId.class),
*通過指定複合類去指定主鍵,同樣複合物件的實體類,需要通過@javax.persistence.Embeddable
*去修飾,使用還註解,一定要在持久化類中定義複合物件實體類的一樣的屬性,(必須一樣),同時用@Id去修飾
**/
public enum Status {
ONLINE,OFFLINE;
}
@Embeddable
public class Name implements java.io.Serializable {
private String first;
private String last;
//省略set、get自行補充。
}
@javax.persistence.Embeddable
public class ArtitleId implements java.io.Serializable {
//複合屬性作為主鍵需要實現序列化介面
private Integer titleid;
private Integer contentid;
public Integer getTitleid() {
return titleid;
}
public void setTitleid(Integer titleid) {
this.titleid = titleid;
}
public Integer getContentid() {
return contentid;
}
public void setContentid(Integer contentid) {
this.contentid = contentid;
}
//作為主鍵,需要重寫equals和hashcode,能夠唯一區分該物件
}
到了這,實體類的對映關係,設定差不多,怎麼去根據實體類生成呢,這個和之前的資原始檔不同,需要做如下的修改:
<mapping class="com.example.test.bean.Artitle"/>//指定你的持久化類