最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java的Hibernate框架中的基本映射用法講解

 更新時間:2016年07月05日 08:58:27   作者:zhang_xinxiu  
映射是Hibernate框架操作數(shù)據(jù)庫數(shù)據(jù)的重要特性之一,這里我們來看一下Java的Hibernate框架中的基本映射用法講解,包括最基本的單向一對一與多對一映射關系等:

Hibernate進行了分類整合發(fā)現(xiàn)其實Hibernate分為三大部分:核心對象、映射、HQL,這三大部分開發(fā)過程中最常使用,前幾篇討論了核心對象及對象之間的轉(zhuǎn)換方法,接下來討論Hibernate的映射使用方法。
 
Hibernate一個重要的功能就是映射,它能夠在對象模型和關系模型之間轉(zhuǎn)換,是面向?qū)ο缶幊趟枷胩岢褂玫?,使用映射程序開發(fā)人員只需要關心對象模型中代碼的編寫。對象和關系數(shù)據(jù)庫之間的映射通常是由XML文檔來定義的。這個映射文檔被設計為易讀的,并且可以手動修改。這種映射關系我總結為下圖:

20167590517885.png (442×305)

映射是通過XML來定義的,使用Hibernate創(chuàng)建的session來管理,最后由session使用JTA把更改提交到數(shù)據(jù)庫中。session可以理解為持久化管理器,管理持久層中的對象,它是由sessionFactory創(chuàng)建的。使用Hibernate編程時首先要連接數(shù)據(jù)庫,所以首先要去查看xml中有關數(shù)據(jù)庫連接的配置,根據(jù)文檔的配置創(chuàng)建sessionFactory(可以理解為數(shù)據(jù)庫鏡像),再由sessionFactory創(chuàng)建一個session,最后由session統(tǒng)一將更改提交到數(shù)據(jù)庫,這才完成了一部所有的操作。


使用過程
1.創(chuàng)建映射文件,映射文件以.hbm.xml為后綴名,標明它是Hibernate的映射文件;
2.在映射文件中注冊實體類,并將實體類的屬性添加到映射類中,在添加屬性時要指定兩種值分別是id和property,id指明它是一個實體的唯一標示,property指明它是表的字段列;
3.提交修改,同步數(shù)據(jù)。
Note:開發(fā)過xml數(shù)據(jù)轉(zhuǎn)到數(shù)據(jù)庫的開發(fā)人員很快就能理解這種映射其實是一種批量更新、批量創(chuàng)建的過程,映射也不例外,Hibernate規(guī)定了一套映射標準,按照標準就能夠?qū)崿F(xiàn)轉(zhuǎn)換,它的內(nèi)部實現(xiàn)還是死的,所以它只是相對的靈活易用。

一個簡單的實體類映射過程:
1. 實體類User1的屬性代碼:

package com.hibernate; 
 
import java.util.Date; 
 
public class User1 { 
 private String id; 
 private String name; 
 private String password; 
 private Date createTime; 
 private Date expireTime; 
 public String getId() { 
  return id; 
 } 
 public String getName() { 
  return name; 
 } 
 public void setName(String name) { 
  this.name = name; 
 } 
 public String getPassword() { 
  return password; 
 } 
 public void setPassword(String password) { 
  this.password = password; 
 } 
 public Date getCreateTime() { 
  return createTime; 
 } 
 public void setCreateTime(Date createTime) { 
  this.createTime = createTime; 
 } 
 public Date getExpireTime() { 
  return expireTime; 
 } 
 public void setExpireTime(Date expireTime) { 
  this.expireTime = expireTime; 
 } 
  
} 

 
2. User1.java的映射文件User1.hbm.xml的內(nèi)部代碼實現(xiàn):
基礎數(shù)據(jù)庫中能夠設置的在Hibernate中同樣提供了設置的方法,可以使用標簽屬性來設置具體的映射關系。
類-->表使用class標簽,常用屬性:
(1)name:映射實體類,它的值需要設置為需要轉(zhuǎn)化成表的實體類的名稱,在同步時會根據(jù)該屬性查找相應的實體類。
(2)table:映射數(shù)據(jù)庫表的名稱,如果要映射的表的名稱和實體類名稱不相同,使用該屬性來指定映射的表,如果不存在的話會根據(jù)該屬性值創(chuàng)建一個表。
 查看上圖中配置生成的表結構,如下圖:

20167590554195.png (522×187)

其中的表名更改為了t_user1;id字段更名為user_id,字段長度為32位;createTime屬性,映射為數(shù)據(jù)庫字段create_time,并修改為date類型。
屬性-->字段使用id或property標簽,常用屬性:
(1)name:功能類似于class標簽的name,值定實體類的映射屬性名;
(2)column:類似于實體類class標簽的table,指定映射表的列名稱,如果不存在將會創(chuàng)建;
(3)type:指定映射到數(shù)據(jù)庫中字段的數(shù)據(jù)類型,根據(jù)需要查看文檔即可;
(4)generator,它是可選的,用來為一個持久類生成唯一的標識。

<id name="id" type="long" column="cat_id"> 
  <generator class="org.hibernate.id.TableHiLoGenerator"> 
    <param name="table">uid_table</param> 
    <param name="column">next_hi_value_column</param> 
  </generator> 
</id> 

 
所有的生成器都實現(xiàn)org.hibernate.id.IdentifierGenerator接口。 這是一個非常簡單的接口;某些應用程序可以選擇提供他們自己特定的實現(xiàn)。當然, Hibernate提供了很多內(nèi)置的實現(xiàn)。下面介紹常用的幾種:
(1)identity:返回的標識符是long, short 或者int類型的。類似于數(shù)據(jù)庫的自增字段。
(2)sequence:在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的標識符是long, short或者 int類型的。在整個數(shù)據(jù)庫中自增,而不是單個的表中自增,需要指定單個的表中自增需要添加屬性。
(3)uuid:用一個128-bit的UUID算法生成字符串類型的標識符, 這在一個網(wǎng)絡中是唯一的(使用了IP地址)。UUID被編碼為一個32位16進制數(shù)字的字符串。類似于.NET生成的序列號。
(4)native:根據(jù)底層數(shù)據(jù)庫的能力選擇identity, sequence 或者hilo中的一個。靈活的方式,會根據(jù)使用的數(shù)據(jù)庫來確定使用的標識類型,MySQL會選擇identity,Oracle選擇sequence。
(5)assigned:手動為實體類制定一個標識id。這是 <generator>元素沒有指定時的默認生成策略。
(6)foreign:使用另外一個相關聯(lián)的對象的標識符。通常和<one-to-one>聯(lián)合起來使用。
開發(fā)人員往往習慣了手動配置的方法根據(jù)文檔的說明來編寫配置屬性,這樣做很原始,初學者建議采用手動配置的方法,有助于思考。另外還有很多第三方工具,通過可視化的方法來配置然后生成xml配置文檔,提高了開發(fā)效率,類似的工具如:XDoclet、Middlegen和AndorMDA。
 
關聯(lián)映射之多對一
上面討論了Hibernate的基本映射,一個實體類對應著一張表,在相應的Hibernate Mapping文件中使用<class>標簽映射。并且實體類中的普通屬性對應著表字段,使用<property>標簽映射。另外在構造實體類時應注意:在實體類中應實現(xiàn)無參的默認的構造函數(shù),提供一個標示,建議不要使用final修飾實體類,為實體類生成getter和setter方法,最后介紹了幾種主要的主鍵生成策略,接下來討論多對一映射。

20167590613848.png (818×282)

這種多對一關聯(lián)映射反應到對象模型中它是一種聚合關系,User是group的一部分,group中存在User,它們兩個的生命周期是不相同的,可反應為下圖:

20167590632092.png (488×252)

那么這種多對一關系映射在Hibernate中是如何設置的呢?下面將會介紹兩種方法,使用<many-to-one>標簽直接映射,或者使用<many-to-one>的cascade級聯(lián)修改表。
 1、Many-to-one直接映射
從字面意思上就能夠理解,它是指多對一的關系,many指的是多的一端,one指的是少的一端,在使用時往往在多的一端的hbm中使用該標簽,并將<many-to-one>的name屬性設置為該映射文件對應的類中的one一端的屬性,如:<many-to-one name="group" column="groupid"></many-to-one>,該標簽添加在了User.hbm.xml中,它對應many;標簽中的name值為group對映射one,并且在User.java中會有一個名為group的屬性。接下來看下具體實現(xiàn)實現(xiàn)的代碼類。
(1)User.java類代碼,其中有一個名為group的屬性,它將會作為<many-to-one>的one一端的name值。

public class User { 
 private String name; 
 public String GetName(){ 
  return name; 
 } 
 public void SetName(String name){ 
  this.name=name; 
 } 
  
 private Group group; 
 public Group GetGroup(){ 
  return group; 
 } 
 public void SetGroup(Group group){ 
  this.group=group; 
 } 
} 

(2)User.hbm.xml中的<many-to-one>,name的值為User.java中one端的屬性值,它會在數(shù)據(jù)庫中生成一個新列,可以將該新列理解為User表的外鍵。

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<!-- Generated 2014-5-14 23:39:25 by Hibernate Tools 3.4.0.CR1 --> 
<hibernate-mapping> 
 <class name="com.hibernate.User" table="USER"> 
  <id name="id" type="java.lang.Long"> 
   <column name="ID" /> 
   <generator class="assigned" /> 
  </id> 
   
  <!-- name的值group為User.java中的一個對應的one中的一個屬性,它會自動在表中生成一列,所以使用column對列進行了重命名 --> 
  <many-to-one name="group" column="groupid"></many-to-one> 
   
 </class> 
</hibernate-mapping> 

(3)測試上面的映射關系,向表中寫入兩個User對象分別為user1和user2,命名為張三和李四,使用session保存對象,向數(shù)據(jù)庫中寫入數(shù)據(jù),代碼如下:

public void testSave1(){ 
   
  Session session=null; 
  try{ 
   session=GetSession.getSession(); 
   session.beginTransaction(); 
    
   Group group=new Group(); 
   group.SetName("動力節(jié)點"); 
    
   User user1=new User(); 
   user1.SetName("張三"); 
   user1.SetGroup(group); 
    
   User user2=new User(); 
   user2.SetName("李四"); 
   user2.SetGroup(group); 
    
   session.save(user1); 
   session.save(user2); 
    
   //會報TransientObjectException錯誤 
   //在清理緩存時發(fā)生錯誤TransientObjectException 
   //因為Group為Transient狀態(tài),沒有被Session,在數(shù)據(jù)庫中沒有匹配的數(shù)據(jù) 
   //而User為Persistent狀態(tài),在清理緩存時Hibernate在緩存中無法找到Group對象 
   //揭露:Persistent狀態(tài)的對象不能引用Transient狀態(tài)的對象 
   //該問題在testSave2方法中更改 
   session.getTransaction().commit(); 
  }catch(Exception e){ 
    
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally{ 
   GetSession.CloseSession(session); 
  } 
 } 

但是使用上面的代碼在執(zhí)行寫入時會報錯TransientObjectException,這是因為在保存User對象時它會按照<many-to-one>中添加的group去內(nèi)存中查找group對象,但是上面的代碼中group對象一直都是在Transient狀態(tài)中,并沒有被session管理,也就是說查找不到session對象,而User對象進入了Persistent狀態(tài),于是會報此錯誤。正確的代碼如下:

public void testSave2(){ 
    
 Session session=null; 
 try{ 
  session=GetSession.getSession(); 
  session.beginTransaction(); 
   
  Group group=new Group(); 
  group.SetName("動力節(jié)點"); 
  session.save(group);  //此處將group對象設置為Persistent對象 
   
  User user1=new User(); 
  user1.SetName("張三"); 
  user1.SetGroup(group); 
   
  User user2=new User(); 
  user2.SetName("李四"); 
  user2.SetGroup(group); 
   
  session.save(user1); 
  session.save(user2); 
   
  //可以正確的保存數(shù)據(jù) 
  //因為Group和User都是Persistent狀態(tài)的對象 
  //所以在Hibernate清理緩存時在session中可以找到關聯(lián)對象 
  session.getTransaction().commit(); 
 }catch(Exception e){ 
   
  e.printStackTrace(); 
  session.getTransaction().rollback(); 
 }finally{ 
  GetSession.CloseSession(session); 
 } 
} 

2、級聯(lián)映射
除了上面所說的將group對象和user對象都轉(zhuǎn)化到Persistent對象外,還可以使用cascade級聯(lián)映射屬性,在<many-to-one>屬性中添加cascade屬性,并復制為save-update,在group對象并非為Persistent狀態(tài)時即可寫入數(shù)據(jù)庫。這樣只需要將兩個user對象的Group屬性設置為同一個group對象即可實現(xiàn)多對一的映射關系,此時User.hbm.xml中對應的內(nèi)容為如下代碼:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<!-- Generated 2014-5-14 23:39:25 by Hibernate Tools 3.4.0.CR1 --> 
<hibernate-mapping> 
 <class name="com.hibernate.User" table="USER"> 
  <id name="id" type="java.lang.Long"> 
   <column name="ID" /> 
   <generator class="assigned" /> 
  </id> 
   
  <!-- 級聯(lián)修改表 --> 
  <many-to-one name="group" column="groupid" cascade="save-update"></many-to-one> 
   
 </class> 
</hibernate-mapping> 

 
Note:cascade設置為save-update后即可實現(xiàn)向數(shù)據(jù)庫中級聯(lián)修改、添加和刪除,但是具體的級聯(lián)查詢操作卻不可以。
對應的測試配置文件的方法為如下代碼:

//級聯(lián)cascade 
public void testSave3(){ 
  
 Session session=null; 
 try{ 
  session=GetSession.getSession(); 
  session.beginTransaction(); 
   
  Group group=new Group(); 
  group.SetName("動力節(jié)點"); 
   
  User user1=new User(); 
  user1.SetName("張三"); 
  user1.SetGroup(group); 
   
  User user2=new User(); 
  user2.SetName("李四"); 
  user2.SetGroup(group); 
   
  session.save(user1); 
  session.save(user2); 
   
  //沒有拋出TransientObjectException異常 
  //因為使用了級聯(lián) 
  //Hibernate會首先保存User的關聯(lián)對象Group 
  //Group和User就都是Persistent狀態(tài)的對象了 
  session.getTransaction().commit(); 
 }catch(Exception e){ 
  e.printStackTrace(); 
  session.getTransaction().rollback(); 
 }finally{ 
  GetSession.CloseSession(session); 
 } 
} 

3、對比升華
 兩種方法同樣實現(xiàn)了多對一的映射方法,結果上是相同的,但在實現(xiàn)上很不相同。無論是第一種還是第二種采用的都是<many-to-one>在many一端的映射文件中添加該標簽,并將標簽的name屬性賦值為該映射文件注冊的類中的one一端的屬性值,這樣就完成了多對一的基本映射,這是相同點。不同點是直接映射關系沒有采用Hibernate字段的屬性,這樣在實現(xiàn)上較靈活,不但支持增刪改,而且可以查詢;第二種的cascade級聯(lián)修改則采用了Hibernate提供的方法,此種方法只支持增刪改,并不支持查詢。

相關文章

最新評論

永济市| 淮阳县| 东兴市| 望城县| 黎平县| 抚顺市| 松原市| 合肥市| 乳山市| 东海县| 宁国市| 霞浦县| 介休市| 平罗县| 中宁县| 仙桃市| 扎赉特旗| 陵川县| 阿图什市| 潞西市| 德州市| 望都县| 电白县| 锦州市| 永州市| 康保县| 枣庄市| 吉林市| 浦北县| 库伦旗| 商水县| 神木县| 垦利县| 赫章县| 吕梁市| 德州市| 麻栗坡县| 山阴县| 郎溪县| 红原县| 微博|