Hibernate技術文檔
hibernate數據持久化組件
對象持久化,把數據保存在永久的存儲介質中(數據庫)
OR/M(object relationmapping)對象關系映照。
POJO類,就是標準的Java Bean。
Hibernate就是1個可以自動的根據xml完成對象關系映照,并持久化到數據庫的開源組件。
Hibernate的底層也是有JDBC實現的。
hibernate是通過xml文件的配置,對數據庫的底層的方言,和數據庫連接所需的信息,和連接數據庫的驅動。hibernate的系統配置文件的名字1般叫做hibernate.cfg.xml,
1般是映照類名加.hbm.xml。1般將映照類的xml文件和實體類放在1起。
hibernate.cfg.xml中會設置數據庫的連接信息,和援用的其他文件的文件名,和1些其他的攝制。這個文件1般放在項目的根目錄下。
在hibernate.cfg.xml的寫法
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/HibernateConfiguration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration⑶.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="show_sql">true</property><!--顯示sql語句-->
<propertyname="format_sql">true</property><!--使顯示的sql語句格式化-->
<property name="dialect">....</property><!--使用的數據庫方言信息-->
<propertyname="connection.driver_class">....</property>
<!--使用的數據庫的驅動-->
<propertyname="connection.url">....</property><!--連接數據庫使用的url-->
<propertyname="connection.username">...</property>
<!--連接數據庫的用戶名-->
<propertyname="connection.password">...</property>
<!--連接數據庫的密碼-->
<mappingresource="xxx/xxxx/Xxxxxx.hbm.xml"/>
<!--引入的映照對象的xml文件的全路徑及文件名-->
</session-factory>
</hibernate-configuration>
hibernate的映照類的XXXX.hbm.xml的寫法
<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/HibernateMapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping⑶.0.dtd">
<hibernate-mapping package="XXX.XXX.XXX"><!--映照類所在的包-->
<classname="Xxxxxx" table="Xxxxx"><!--將類和數據庫的表聯系起來-->
<idname="studentId" column="studentId"><!--主鍵生成策略-->
<generatorclass="assigned"/>
<!--指定主鍵生成策略為用戶指定-->
</id>
<propertyname="XXX" column="XXXX" type="string"/>
<!--類中的書性和字段之間建立聯系-->
<property name="homeAddress"column="homeAddress"/>
<propertyname="schoolAddress" column="schoolAddress"/>
<propertyname="brithday" column="brithday"type="data"/>
<!--在hibernate中其他類型可以自動辨認只有Data類型必須指名-->
</class>
</hibernate-mapping>
使用hibernate編程步驟
1,配置環境,加載hibernate的jar文件,和連接數據庫連接使用的jar文件,并配置CLASSPATH環境變量。
2,寫hibernate所需的配置文件,hibernate.cfg.xml ,Xxxxx.hbm.xml
3,寫POJO類
4,調用hibernate API。
1)使用Configuration對象的buildSessionFactory()方法創建SessionFactory對象
2)使用SessionFactory對象openSession()方法創建Session對象。
3)使用Session的相應方法來操作數據庫,將對象信息持久化到數據庫。
hibernate的配置文件hibernate.cfg.xml用于配置數據庫的連接的信息,和需要持久化的對象的xml映照文件的位置
在hibernate.cfg.xml中使用<mappingresource="xml/Student.hbm.xml">這類方式來指名要持久化對象的映照文件。
Configuration是用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并產生SessionFactory對象。
SessionFactory是和1個數據庫逐一對應的,他只能對應1個hibernate.cfg.xml文件,1個hibernate.cfg.xml中只能配置1個數據庫的連接信息。
POJO(普通的java類)
持久化對象和臨時對象,持久化對象,即對象的信息在數據庫中存在,在內存中也有。臨時對象也就是新對象,沒有同步到數據庫。
Session,持久化管理器。
Hibernate的核心接口
1.Configuration,用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并創建SessionFactory對象。
2.SessionFactory,用于創建Session對象。
3.Session,持久化管理器,對象級數據庫操作
4.Query,對對象作持久化操作或查詢操作
5.Transaction ,用于管理操作事務。
hibernate.cfg.xml中的標簽
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/HibernateConfiguration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration⑶.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="show_sql">true</property><!--顯示sql語句-->
<propertyname="format_sql">true</property><!--使顯示的sql語句格式化-->
<propertyname="dialect">....</property><!--使用的數據庫方言信息-->
<propertyname="connection.driver_class">....</property>
<!--使用的數據庫的驅動-->
<propertyname="connection.url">....</property><!--連接數據庫使用的url-->
<propertyname="connection.username">...</property>
<!--連接數據庫的用戶名-->
<propertyname="connection.password">...</property>
<!--連接數據庫的密碼-->
<mappingresource="xxx/xxxx/Xxxxxx.hbm.xml"/>
<!--引入的映照對象的xml文件的全路徑及文件名-->
</session-factory>
</hibernate-configuration>
對象映照文件
<hibernate-mapping package="XXX.XXX.XXX"auto-import="false"><!--映照類所在的包-->
<classname="Xxxxxx" table="Xxxxx"><!--將類和數據庫的表聯系起來-->
<idname="studentId" column="studentId"><!--主鍵生成策略-->
<generatorclass="assigned"/>
<!--指定主鍵生成策略為用戶指定-->
</id>
<propertyname="XXX" column="XXXX" type="string"/>
<!--類中的書性和字段之間建立聯系-->
<propertyname="homeAddress" column="homeAddress"/>
<propertyname="schoolAddress" column="schoolAddress"/>
<propertyname="brithday" column="brithday"type="data"/>
<!--在hibernate中其他類型可以自動辨認只有Data類型必須指名-->
</class>
</hibernate-mapping>
id生成方式
1,序列sequence 只適用于Oracle
<id name="id" column="id">
<generatorclass="sequence">
<paramname="sequence">person_seq</param><!--指定sequence名-->
</generator>
</id>
2,自增列,適用于SQLServer
<id name="id" column="id">
<generatorclass="identity"/>
</id>
3,取最大值加1
<id name="id" column="id"type="integer">
<generatorclass="increment"/>
</id>
4,根據底層數據庫指定生成方法
<id name="id"column="id">
<generatorclass="native"/>
</id>
針對Oracle數據庫的生成方式還是sequence,只不過需要1個特定名字的sequence,"hibernate_sequence"。
5,高低位算法
<id name="id" column="id">
<generatorclass="hilo">
<paramname="table">high_value</param>
<!--設置高位值取值的表-->
<paramname="column">next_value</param>
<!--設置高位值取值的字段-->
<paramname="max_lo">50</param>
<!--指定低位最大值,當取道最大值是會再取1個高位值再運算-->
</generator>
</id>
類關聯關系映照
1對1關系實現
建表策略
1,同享主鍵,也就是1方援用另外一方的主鍵,作為本身的主鍵,也是外鍵。
2,外鍵援用,也就是1方援用另外一方的主鍵,作為外鍵,并且對援用的外鍵加唯1束縛。
1對多
建表策略,多方援用1方的主鍵當作外鍵
持久化對象,即就是在數據庫中存有其相對應數據的對象,并且在內存中也有這個對象,這個對象在Session的管理范圍內,也就是調用過save()方法同步到數據庫的對象。
臨時對象,即在內存中剛剛創建的對象,還沒有同步到數據庫,或是數據庫中信息被刪除的對象也是臨時狀態。
游離對象,也就是在數據庫中有和該對象向對應的紀錄,并且在內存中的也存在該對象,但是不在Session的管理范圍以內,也就是在Session關閉以后,就成了游離對象,就不會在將其改變同步到數據庫中,如果要使還想令其成為持久化對象就要在把它納入Session管理中,也就是掉用Session中的update()方法就能夠了。
及物的持久化,也就是說針對這個對象的屬性進行持久化操作,也就是通過級聯進行設置。
以下是1對多中1端set標簽的設置
<set name="st" inverse="true"cascade="delete" batch-size="3">
<keycolumn="cid"/>
<one-to-manyclass="Student"/>
</set>
inverse="true"就是在設置如果在內存中的修改或添加了這個集合中的某1個或某幾個對象他不會將全部集合的信息同步到數據庫,而是只將集合中被修改的對象重新同步到數據庫。
cascade屬性是設置級聯操作的也就是在操作1真個數據如果影響到多端數據時會進行級聯操作,
cascade="none",cascade="save-update",cascade="delete",cascade="all"cascade="persist"
cascade="delete-orphan",cascade屬性的值經常使用的設置為以上5項:
none就是不使用級聯操作,默許級聯是none。
save-update也就是只有對象保存操作(持久化操作)或是持久化對象的更新操作,才會級聯操作關聯對象(子對象)。
persist就只是將級聯對象也持久化到數據庫。
delete對持久化對象的刪除操作時會進行級聯操作關聯對象(子對象)。
all對持久化對象的所有操作都會級聯操作關聯對象(子對象)。
all-delete-orphan,在多端進行刪除操作時,會再多端表中留下null空紀錄,設置了級聯操作為delete之會將表中表示關聯的外鍵id置成null,不會將這條紀錄也刪除掉,而把級聯設置成delete-orphan就不會留有空紀錄,而是級聯的把相干紀錄刪除掉。
batch-size這個屬性只能夠寫在set標簽中,這個屬性帶表批量加載,也就是在加載1真個集合屬性時會1次加載指定的數量的對象,而不是默許的1個1個的加載,會提高效力,批量加載只能用于延遲加載和立即加載策略,也就是(lazy="true"或lazy="false")。
lazy="true"延遲加載,所謂的延遲加載,就是對1真個集合屬性的加載策略,就是在不使用到集合中的對象的數據就不會真實的加載集合中的對象數據,而是家在1個代理對象就相當于的1個空的容器。這也就是會出現LazyInitializationException異常,也就是沒有初始化這個代理的集合對象,在事前查詢到了集合中的對象就會初始化這個對象,如果Session沒有關閉就會在查詢加載集合中的對象信息,如果提早關閉了Session,當使用集合中的對象信息時就會有這個異常。
fetch="join",這就是使用了預先抓取策略,也就是針對關聯的對象的加載策略,在使用到關聯對象的信息時會再發送sql語句,如果不使用fetch="join",就會不使用表連接而是先查出1真個關聯id再1條1條的發送sql語句查詢到關聯對象信息,使用了fetch="join"就會使用表連接將關聯對象信息直接查尋出來的。fetch="lazy"這個是默許的設置。
注意:
在使用fetch="join"要辨別開他和外連接的區分,他不會疏忽配置文件中的加載策略,而使用了外連接就會疏忽配置文件中使用了外連接的1真個所有加載策略,而替之為立即加載。
例:班級 tream,身份證 Certigicate 學生 student
身份證和學生是1對1關系,班級和學生是1對多的關系。學生對身份證的加載策略是預先抓取,學生對班級是預先抓取,但是班級對學生是延遲加載。
現在使用了外連接
Query q=session.createQuery("from Student as s left joins.team");
as 的語法是取別名的語法。
也就是使用了外連接的來查尋班級,這樣就會疏忽,學生對象對其所有屬性除使用外連接查尋的屬性,而其余都會使用立即加載。
<property name="" column="" type=""not-null="true">,這樣也就會使這個屬性不能夠為空值
查詢對象,可使用get()和load()方法,不過條件是必須知道該對象持久化時的唯1標識,也就是id,和這個對象的類對象。
hibernate的HQL中的select和update語法
select 別名 from 類全名 別名 where 別名.類屬性=:變量名
如果要查尋全部可以簡寫為from 類全名
update 類全名 set 屬性名=:變量名 where 屬性名=:變量名
注意以上這些語句要在createQuery("...")中。
多對多的映照實現
1般多對多關聯會拆分成兩個1對多的關系來實現多對多關系,也能夠通過hibernate提供的解決方案來實現。其實hibernate的實現方式是通過中間表間接的實現了多對多關系,實際上也是將多對多拆分成兩個雙向的1對多關系。
多對多關系XML文件的配置
<hibernate-mapping>
<class name="Course" table="course">
<set name="clazz"table="class_course" inverse="true"><!--設置中間表的表名-->
<keycolumn="courseid">
<many-to-manycolumn="classid" class="Clazz"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="Clazz" table="class">
<setname="course" table="class_course"cascade="save-update">
<keycolumn="classid"/>
<many-to-many column="courseid"class="Course"/>
</set>
</class>
</hibernate-mapping>
類繼承關系映照
建表策略
1.所有類建1個表,只為具體類建表,每一個類建1個表。
2.只為具體類建表,使用于不使用多態的情況下,具體類之間沒有繼承關系時適用
3.需要針對每一個類寫映照配置文件,就和普通的單表映照的xml文件相同。
4.也能夠使用1個xml文件來進行映照,可以通過寫union-subclass標簽來表現其關系
5.這里不能使用id生成策略中的native,而是要指定特定的生成策略。
例:
<union-subclass name="notpad"table="tpcc_notpad">
<property name="wight" column="wight"type="integer"/>
</union-subclass>
<union-subclass name="desktop"table="tpcc_desktop">
<propertyname="LCD" column="isLCD" type="yes_no"/>
</union-subclass>
每一個類建1個表,可以有效減少數據的冗余,減少字段,查詢效力不很高。
正對每一個類建1個表,只要寫1個配置文件來進行類的映照便可
映照文件中的子類可使用join-subclass標簽來表示,并且援用父類的主鍵作為同享主鍵,就是不需要指定id生成策略
例:
<hibernate-mapping package="alan.hbn.rel.inherit"auto-import="false">
<classname="Computer" table="tph_computer">
<idname="comid" column="comid" type="long"unsaved-value="0">
<generatorclass="identity"/>
</id>
<propertyname="price" column="price" type="integer"/>
<joined-subclassname="notpad" table="tpc_notpad">
<key column="comid" />
<property name="wight"column="wight" type="integer"/>
</joined-subclass>
<joined-subclassname="Guest" table="tpc_guest">
<key column="comid"/>
<property name="LCD"column="isLCD" type="yes_no"/>
</joined-subclass>
</class>
</hibernate-mapping>
所有類只建1個表,查尋效力比較高,但是會產生很多空間浪費,當子類中的非空束縛,就不大適用了,這是對子類可使用subclass標簽表示。
<hibernate-mapping package="alan.hbn.rel.inherit"auto-import="false">
<classname="Computer" table="tph_computer">
<idname="id" column="id" type="long"unsaved-value="0">
<generatorclass="identity"/>
</id>
<discriminatorcolumn="computer_type" type="integer"/>
<propertyname="price" column="price" type="integer"/>
<subclassname="Administrator" discriminator-value="ad">
<propertyname="wight" column="wight" type="integer"/>
</subclass>
<subclass name="Guest"discriminator-value="gu">
<property name="LCD"column="isLCD" type="yes_no"/>
</subclass>
</class>
</hibernate-mapping>
不斟酌多態時,最好是用只針對具體類建表,而斟酌多態時盡可能使用所有類建1個表,只有當子類中的屬性過量是才斟酌每一個類建1個表的策略。
Hibernate控制的事務
事務保證原子操作的不可分,也就是操作的同時成功或同時失敗。
Transactiontran=session.beginTranaction();
tran.commit();
tran.rollback();
以上是事務對象的方法,來實現對事務的支持。
hibernate的事務隔離級別
hibernate的事務隔離級別和JDBC中大致相同。
設置時要在hibernate.cfg.xml配置
<propertyname="hibernate.connection.isolation">4</property>
1,讀未提交的數據(Read uncommitted isolation)
2,讀已提交的數據(Read committed isolation)
4,可重復讀級別(Repeatable read isolation)
8,可串行化級別(Serializable isolation)
hibernate的鎖(悲觀鎖,樂觀鎖)
悲觀鎖是由數據庫本身所實現的,會對數據庫中的數據進行鎖定,也就是鎖行。
LockMode.UPGRADE,修改鎖,在get()方法中加上這個設置作為第3個參數。
LockMode.NONE 無鎖機制
LockMode.READ 讀取鎖
LockMode.WRITE 寫入鎖,不能在程序中直接使用
還可使用Session.lock()Query.setLockMode() Criteria.setLockMode()方法來設置鎖
樂觀鎖,也就是通過對記錄加上某些信息來解決并發訪問的問題。
版本檢查
要在其表中多加上1列表示版本信息,會在讀取時讀到這個版本號,并在修改以后更新這個版本號,并且只有版本號相同才會予以更新,如果版本號低,就會拋出例外。
<versionname="version" column="version" type="integer"/>
時間戳
使用時間戳,是通過最后修改時間來判斷是不是來做更新操作,也就是只有在最后更新時間以后才會做更新。
<timestampname="updateTime" column="updatetime"/>
hibernate組件映照
組件不會生成唯1標識,但是也需要對應實體類。
hibernate中可以把1個類的對象當作1個屬性組件來使用,并且在使用時會自動創建,所以同1組件對象是不會被兩次援用的。
例:
<hibernate-mappingpackage="alan.hbn.rel.inherit" auto-import="false">
<class name="Guest"table="guest">
<id name="id"column="id" type="long" unsaved-value="0">
<generatorclass="native"/>
</id>
<propertyname="userName" column="userName"type="string"/>
<propertyname="password" column="pwd" type="string"/>
<propertyname="birthday" column="birthday"type="date"/>
<componentname="homeAddress" class="Address">
<propertyname="street" column="street"type="string"/> <propertyname="zipcode" column="zipcode" type="string"/> </component>
</class
</hibernate-mapping>
hibernate的HQL(hibernate Query Language)
HQL是hibernate的查詢語言,他可以支持面向對象的查詢。使用HQL語句,只能通過session.createQuery("...")。
使用hibernate分頁顯示,使用Query對象的setFirstResult(int firstResult)(firstResult從零開始)方法和setMaxResults(int maxResults) 方法。他會根據不同的底層數據庫來顯示指定數量的記錄。