日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【大话Hibernate】Hibernate两种实体关系映射详解

發布時間:2024/4/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【大话Hibernate】Hibernate两种实体关系映射详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

實體類與數據庫之間存在某種映射關系,Hibernate依據這種映射關系完成數據的存取,因此映射關系的配置在Hibernate中是最關鍵的。Hibernate支持xml配置文件與@注解配置兩種方式。xml配置文件是最基礎的配置,而@注解是Java的官方JPA(Java?Persistence?API)提供的。本章分別使用@注解與xml講解Hibernate的映射配置。


一、實體類映射:

?

Java的角度講,實體類就是普通的Java封裝類(有人稱為POJO有人稱為VO)。僅從實體類中的代碼信息,Hibernate并不能得知該實體類對應哪個數據表,因此還需要以某種方式配置一下。常用的方式有*.hbm.xml文件配置與@注解配置兩種。

hbm.xml文件就是普通的xml文件,hbmHibernateMapping的縮寫,這樣從文件名上就能判斷該文件為Hibernate實體類配置文件。在JPA出現之前,Hibernate都使用hbm.xml文件配置。JPA出現后,推薦使用JPA@注解配置,因為對于所有的ORM框架,@注解都是通用的。

?

1、@注解配置:

實體類一般有ID、普通屬性、集合屬性等,分別對應數據庫的主鍵、普通列、外鍵。在@注解配置中,實體類用@Entity注解,用@Table指定對應的數據表,用@Id配置主鍵,用@Column配置普通屬性,用@OneToMany、@ManyToOne、@OneToOne、@ManyToMany配置是實體間的關系。

?

2XML配置:

多個實體類可以配置在一個XML文件中。Hibernate推薦用一個同名的XML文件配置一個實體類,便于閱讀和維護。XML文件一般以“*.hbm.xml”結尾,便于辨認,也可以直接使用“*.xml”結尾。

實體類還需要配置到hibernate.cfg.xml中,以便hibernate初始化實體類與數據庫表的映射關系。如果只配置了映射關系,而沒有配置到hibernate.cfg.xml中,hibernate仍然不會知道哪些類是實體類,因為hibernate無法通過遍歷所有的類來決定哪些是實體類。如果實體類是用@注解配置的,需要用<mappingclass=”” />配置,而如果是用XML文件配置的,則需要使用<mappingresource=”” />配置XML配置文件。

?

?

二、主鍵映射:


實體類最好有主鍵列,并有對應的gettersetter方法,這是hibernate推薦的。逐漸盡量使用可以為null值的類型,例如IntegerLongString等,而不要使用intlong等。因為如果主鍵為null,則表示該實體類還沒保存到數據庫,是一個臨時狀態(Transient),而intlong等原始類型則不具備該功能。


1@注解配置主鍵

?????? Hibernate中用@Id聲明該列為主鍵列,同時用@Column聲明該列的列名。當列名與屬性名相同時,@Column配置可省略。@GeneratedValue用于指定主鍵的生成策略。Hibernate支持多種逐漸生成規則,例如自增長、由某個表決定、由Sequence決定等等。如果不配置

?

@GeneratedValue,則必須手動設置ID值。 @Id @Column(name = "id") // 設置主鍵類型, auto表示主鍵是自增長類型 @GeneratedValue(strategy = GenerationType.AUTO) private Integer id;

?

2.??XML文件中配置主鍵


如果使用XML配置,主鍵用<id />配置,name指定實體類的主鍵屬性,column指定數據表中的主鍵列名。使用嵌套的<generator />配置主鍵生成策略,native表示使用數據庫自己的策略,在MySQL中就是自增長類型,如果不用自動增長類型,則可以用assigned,例如:

?

<id name="id" column="id"> <generator class="native" /> </id>

?

?主鍵生成規則

上面說了主鍵的配置,在配置主鍵過程中,配置了主鍵是否是自動生成的。@Id配置主鍵的同時,也要用@GeneratedValue配置主鍵生成規則。主鍵生成規則也成為主鍵生成策略,負責維護新實體的主鍵值。用的最多的策略是自增長策略。Hibernate還支持其他的多種主鍵生成規則。這些生成規則有些是數據庫提供的,有些是Hibernate提供的。

?

1.??使用@注解配置主鍵生成規則

到目前為止,@注解只支持四種逐漸生成策略:GenerationType.AUTOGenerationType.TABLEGenerationType.SEQUENCEGenerationType.IDENTITY,意義分別為:

qGenerationType.AUTO:自動方式,根據底層數據庫自動選擇。如果為MySQL等支持自增長類型的數據庫,則為自增長類型(auto_increment)。

?

qGenerationType.TABLE:使用指定的表來決定主鍵的取值,一般結合@TableGenerator使用,示例代碼如下:

?

@Id @TableGenerator(name = "tb_cat_gen", allocationSize= 1) @GeneratedValue(strategy = GenerationType.TABLE, generator= "tb_cat_gen") private Integer id;

?

qGenerationType.SEQUENCE:使用Sequence來決定主鍵的取值,適合OracleDB2PostgreSQLSAPDB等支持Sequence的數據庫,一般結合@SequenceGenerator使用。注意某些數據庫如Oracle等沒有自增長類型,只能使用Sequence,示例代碼如下:

?

@Id @SequenceGenerator(name = "seq_cat", allocationSize= 25) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator= "seq_cat") @Column(name = "id") private Integer id;

?

qGenerationType.IDENTITY:支持DB2MySQLMSSQLServerSybaseHypersonicSQL數據庫的identit類型主鍵。

?

2.??使用XML文件配置主鍵生成規則

?

XML配置中支持的主鍵生成規則,比使用@注解的配置的主鍵生成規則要多,XML配置中支持的主鍵生成規則有以下幾種:

qnative:取決于數據庫,相當于GenerationType.AUTO

?

qidentity:使用identity類型,相當于GenerationType.IDENTITY

?

qsequence:使用sequence,相當于GenerationType.SEQUENCE。需要指定sequence的名稱,示例代碼如下:

?

<id name="id" type=" java.lang.Integer" column=" id"><generatorclass="sequence"><!--使用sequence主鍵生成規則 --><paramname="sequence">id_sequence</param></generator> </id>

?

qincrement:自增長類型,由Hibernate而不是數據庫維護,因此即使Oracle等不支持自增長類型的數據庫也可以使用。

?

qhilohi/low算法,使用指定的表給主鍵賦值,相當于GenerationType.TABLE。需要指定表名、列名等,實例代碼如下:

?

<id name="id" type=" java.lang.Integer" column=" id"><generatorclass="hilo"><paramname="table">users</param><paramname="column">id</param><paramname="max_lo">200</param></generator> </id>

?

qseqhilo:基于sequencehilo算法,例如:

?

<id name="id" type=" java.lang.Integer" column="id"><generatorclass="seqhilo"><param name="sequence">hi_value</param><paramname="max_lo">200</param></generator> </id>

?

quuid:使用128位的UUID算法計算一個唯一的值,會使用IP地址及相關的計算機硬件信息。計算結果為32位的16進制數,對應的主鍵類型必須為String

?

qguid:使用MySQL或者MSSQLServer等數據庫提供的GUID值。

?

qassigned:默認值,不使用任何策略,在保存進數據庫之前必須使用setter方法賦值。

?

qselect:使用數據庫觸發器賦值。

?

qforeign:使用外鍵賦值,在一對一實體關系時,可保證關系雙方的Id保持一致。

MySQL數據庫與Hibernate都提供自增長策略,但是原理是不太一樣的。如果采用MySQL的自增長,插入數據時Hibernate生成的SQL語句中將不包含id主鍵列數據。該主鍵的當前值、下一個值由數據庫自己維護。如果使用Hibernate的自增長,插入數據時Hibernate生成的SQL語句將包含id主鍵列,并由Hibernate維護該主鍵的當前值以及下一個值。

對于普通的應用來說,數據庫自增長與Hibernate自增長在使用上沒有區別。但是如果某數據庫同時被兩個Hibernate程序使用,那么此時使用Hibernate自增長將會出現錯誤。例如如果當前主鍵值為101,那么Hibernate會認為下個主鍵值為102,兩個Hibernate程序插入數據時都會將主鍵值設為101,這時會因為主鍵沖突而導致其中一個寫數據失敗。

?

?

????? 三、普通屬性映射:


?????? 普通屬性是指除了主鍵外的、java基本類型的屬性,例如Integer(int)Long(long)Short(short)Boolean(boolean)Double(double)Float(float)String(string)Date等類型屬性。注意Integer類型與int類型是不同的,Integer默認為null,在數據庫中也表現為null,而int默認為0,在數據庫中也表現為0.

?????

? 1@配置普通屬性

普通屬性使用@Column@Basic配置。二者都可以省略。如果省略,則全部按照默認的規則配置,@Column@Basic的用法如下:

?

@Column中可指定nullable(是否允許為null)、unique(是否唯一)、insertable(是否允許插入)、updatable(是否允許更新)、length(列長度)、columnDefinition(列類型)、scale(整數長度)、precision(小數點精度)等。這些屬性用于生成DDL建表語句。如果屬性對應的列名與屬性名一致,@Column可以省略。

?

q@Basic可為普通屬性配置加載方式,默認為即時加載。如果列數據比較大,例如大文本類型或者LOB類型,可配置為延遲加載。optional配置該列是否可為null。如果為true,表示該屬性是可選的,可以為null,否則不可以為null

@Column@Basic使用的代碼示例如下:

?

@Column(name = "usersName", nullable = true, columnDefinition ="varchar", insertable= true, length = 255, unique = true, updatable= true, precision = 2, scale = 4) @Basic(fetch = FetchType.LAZY, optional=true) private String usersName;

?

2 、使用XML文件配置普通屬性映射

XML中使用<property/>標簽配置普通屬性。type屬性指定列類型,相當于@Column中的columnDefinition。例如,如果設置type=text”可以為String類型屬性設置為大文本類型列。不同于@注解中的@Column,如果屬性名與列名一致,column屬性可省略,xml配置中的<property>必須配置,否則視為不參與持久化的列。配置為:

?

<property name="salary" precision="2"scale="10" length="255" column="salary" type="string" update="true"insert="true" lazy="false" unique="false" not-null="false"> </property>

?

在使用@注解配置中,如果沒有對普通屬性進行配置,則默認該屬性名與數據表列名相同;而xml文件配置中,如果對普通屬性沒有配置,則認為該屬性沒有對應的數據庫列,不參與持久化。二者是截然不同的。

?

?

四、日期屬性配置:


?????? 日期屬性也屬于普通屬性,普通屬性的配置規則也適用于日期屬性。日期屬性又包括只有日期沒有時間(java.sql.Date)、沒有日期只有時間(java.sql.Time)。既有日期又有時間(java.sql.Timestamp)等3種情況,因此要多一些配置。由于java.sql.Datejava.sql.Timejava.sql.Timestamp都是java.util.Date的子類,所以日期屬性直接使用父類java.util.Date就可以了,hibernate會根據日期屬性決定該類型是java.sql.Datejava.sql.Time還是java.sql.Timestamp

?????? 1、使用@注解配置普通屬性映射

?????? 日期屬性也是普通的屬性,需要用@Basic聲明加載方式、@Column等指定列名,二者都可省略。另外,如果日期屬性是java.util.Date類型的,必須要用@Temporal配置日期類型,取值可以為DateTime或者Timestemp。否則Hibernate將無法區分該類型是到底是java.sql.Date(只有年月日等日期信息)類型還是java.sql.Time(只有時分秒等時間信息)類型、還是java.sql.TimeStamp(既有日期信息、又有時間信息)類型。例如:

?

@Temporal(TemporalType.TIMESTAMP)// 日期類型為DATE, TIME或者TIMESTEMP。 @Column(name = " birthday") private java.util.Date birthday;

在配置日期屬性時,如果屬性類型是java.util.Date類型,需要用@Temporal聲明日期類型。但是如果是java.sql.Timejava.sql.Date或者java.sql.TimeStamp類型的,類型本身就已經很明確了,不再需要@Temporal聲明了。

?

2 、使用XML文件配置日期屬性映射

在配置日期類型屬性時,type屬性中指定日期類型,取值可以為datetimetimestamp等簡寫方式,也可以為java.sql.Datejava.sql.Timejava.sql.Timestamp等全寫方式。

同樣的道理,如果Java中屬性類型為java.util.Date類型,必須指定是java.sql.Date(只有年月日等日期信息)類型還是java.sql.Time(只有時分秒等時間信息)類型、還是java.sql.TimeStamp(既有日期信息、又有時間信息)類型。示例代碼如下:

?

<property name=" birthday" type="date"></property>

五、臨時屬性映射:


?????? 實體類可能有一些臨時屬性,在JPA中被稱為Transient屬性。這些屬性用于方便計算等其他用途,而不是保存數據到數據庫中。這些屬性必須被標記為Transient,以便hibernate把他們區別對待。否則hibernate會試圖往數據庫寫該屬性,可能會因對應的列不存在而拋出異常。

?????? 1、使用@注解配置臨時屬性映射

Java標注中,臨時屬性必須使用@Transient標注,既可以配置在臨時屬性上,也可以配置在對應的gettersetter方法上。例如:

?

@Transient public int getCount() {// 臨時屬性,用于計算總記錄數 return name == null ? 0 :count; }

如果只有形如gettersetter的方法,但是沒有對應的屬性,Hibernate仍然會認為該屬性存在。因此也需要用@Transient標注。

??

2 、使用XML文件配置臨時屬性映射


XML配置中,所有沒有配置到XML文件中的屬性都被視為臨時屬性。如果某屬性漏配置了,該屬性值將不被保存到數據庫中。

?

?

?????? 六.版本屬性配置:


?????? Hibernate中有一種特殊的屬性:版本(Version)屬性。版本屬性不參與業務邏輯,只用來保證不會有兩個線程同時對該數據進行寫操作。版本屬性是樂觀鎖的一種實現方法。樂觀鎖是相對于悲觀鎖而言的。


樂觀鎖與悲觀鎖:悲觀鎖與樂觀鎖都是保證數據準確性的機制。


為保證數據的準確性,程序必須保證在一個線程修改數據的時候,該數據沒有被其他線程修改。在傳統的數據庫編程中,程序修改數據時先鎖定該數據行,使其他程序無法修改該行數據,修改完畢后釋放數據鎖,以此保證數據準確性。由于該機制需要鎖定數據行,被鎖定的數據只能被一個線程使用,因此被稱為悲觀鎖。

樂觀鎖使用完全不同的方式。樂觀鎖通過Version列保存當前數據的版本,如果程序修改了數據,就將版本加1。反過來,如果版本列有了變化,說明該數據被修改過了。程序保存數據時會檢查數據的Version列。如果Version列已經發生了變化,程序會重新讀取、修改并保存數據。由于該機制不需要鎖定數據行,允許多條線程同時訪問同一條數據,因此被稱為樂觀鎖。樂觀鎖的效率要高于悲觀鎖,因襲從現代編程中更傾向于樂觀鎖。

在現代的web編程中,開發者已經不需要關心悲觀鎖、樂觀鎖的實現細節,只需要配置一下即可,框架底層會自動實現。


1、悲觀鎖的使用


Hibernate的悲觀鎖是使用SQL語句或者HQL語句實現的,下面是一個典型的倚賴數據庫的悲觀鎖調用:


select * from users wherename=”Jack” for update


這條 sql語句鎖定了users表中所有符合檢索條件(name=Jack”)的記錄。本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。Hibernate的悲觀鎖,也是基于數據庫的鎖機制實現。


下面的代碼實現了對查詢記錄的加鎖:

String hql ="fromUsers where name='Jack';

Query query = session.createQuery(hql);

query.setLockMode("users",LockMode.UPGRADE); //users表進行加鎖

List list = query.list();// 執行查詢,獲取數據

query.setLockMode 對查詢語句中,特定數據庫表的記錄進行加鎖(這里是users表),這里也就是對返回的所有?users記錄進行加鎖。

觀察運行期 Hibernate生成的SQL語句:

select users0_.id asid, users0_.name as name, users0_.group_id

as group_id, users0_.user_type as user_type, users0_.sex as sex

from users users0_?where users0_.name='Jack' ) for update

這里 Hibernate通過使用數據庫的for update子句實現了悲觀鎖機制。


2、樂觀鎖的使用:


Hibernate支持樂觀鎖,保存數據時Hibernate會自動完成檢查Version列、修改數據、更新Version列等工作。Hibernate隱藏了所有的Version操作細節,只需要指定實體類的Version列即可。實體類中可用@Version配置版本屬性。版本列一般為數字類型屬性。例如:


@Version private int version; XML中使用<version />配置樂觀鎖,name屬性配置版本列。注意<version/>版本列要配置在<id/>主鍵后面、<property/>普通屬性前面。例如: <version name="version"></version> XML配置版本屬性要比@配置靈活,版本屬性既可以為int、long等數據類型,也可以為Timestamp時間戳等類型,配置時用type配置類型,例如: <version type="timestamp" column=”version”> 或者直接用<timestemp/>配置日期版本,與上面的配置是等價的: <timestamp column="version">

總結

以上是生活随笔為你收集整理的【大话Hibernate】Hibernate两种实体关系映射详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。