激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 詳解Java的Hibernate框架中的Interceptor和Collection

詳解Java的Hibernate框架中的Interceptor和Collection

2020-03-20 12:13cxshun JAVA教程

這篇文章主要介紹了Java的Hibernate框架中的Interceptor和Collection,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下

Interceptor
講到Interceptor,相信熟悉struts2的童鞋肯定不會(huì)陌生了,struts2可以自定義攔截器進(jìn)行自己想要的一系列相關(guān)的工作。而這里我們說的Interceptor也是差不多相似的功能。
 廢話不說,直接來代碼:
 下面這個(gè)是MyInterceptor類,它實(shí)現(xiàn)了Interceptor接口:

public String onPrepareStatement(String arg0) { 
  return arg0; 
} 
 
public boolean onSave(Object arg0, Serializable arg1, Object[] arg2, 
    String[] arg3, Type[] arg4) throws CallbackException { 
  if (arg0 instanceof User) { 
    System.out.println("User to be saved=>"+((User)arg0).getName()); 
  } 
  return false; 
} 

其他方法就不看了,按默認(rèn)實(shí)現(xiàn)就行,我們只需要改這兩個(gè)方法,需要把onPrepareStatement中的返回值改一下,改成返回當(dāng)前的SQL語句,參數(shù)中就是傳入的執(zhí)行的SQL語句,我們直接返回就可以打印出該語句。
 而在onSave中,看名字就可以知道是在保存的時(shí)候進(jìn)行調(diào)用的。我們可以進(jìn)行一系列保存前的工作。
 相信大家看參數(shù)名稱就可以看明白了吧。
 Serializable是指序列號(hào)的參數(shù),在這里是指跟數(shù)據(jù)庫ID進(jìn)行映射的屬性
 Object[]這是一系列的狀態(tài),暫時(shí)沒怎么用到,以后用到再研究,但API中說明了,不管用何種方式修改了這個(gè)數(shù)組中的值,這個(gè)onSave方法必須返回true。
 String[]是指屬性的名稱
 而Type[]也就是相應(yīng)屬性的類型。
 
 1)這個(gè)Interceptor可以在保存數(shù)據(jù)庫前和后做一些相應(yīng)的操作。比如想對(duì)數(shù)據(jù)進(jìn)行修改,添加前綴或后綴的,都可以用它來實(shí)現(xiàn),下面我們來看一下。

public boolean onSave(Object arg0, Serializable arg1, Object[] arg2, 
    String[] arg3, Type[] arg4) throws CallbackException { 
  if (arg0 instanceof User) { 
    System.out.println("User to be saved=>"+((User)arg0).getName()); 
  } 
  //我們?cè)谶@里添加123作為名字的前綴 
  User user = (User)arg0; 
  user.setName("123"+user.getName()); 
  return false; 
} 

我們看一下測試方法:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Interceptor interceptor = new MyInteceptor(); 
  Session session = sessionFactory.openSession(interceptor); 
     
  User user = new User(); 
  user.setName("shun"); 
     
  Transaction tx = session.beginTransaction(); 
  session.save(user); 
     
  tx.commit(); 
  session.close(); 
     
} 

很簡單,我們只是進(jìn)行了簡單的保存而已。這里就沒給出映射文件和實(shí)體類,大家隨便弄個(gè)試一下就行。
 運(yùn)行它,我們可以看到:

User to be saved=>shun 
Hibernate: insert into USER (USER_NAME, age) values (?, ?) 
Hibernate: update USER set USER_NAME=?, age=? where USER_ID=? 

  它會(huì)在最后進(jìn)行更新姓名和年齡的操作,主要是因?yàn)槲覀冊(cè)趏nSave方法中進(jìn)行了修改。
詳解Java的Hibernate框架中的Interceptor和Collection
我們看到數(shù)據(jù)庫中的值已經(jīng)修改為有123前綴的了。
 
 2)同樣道理,我們可以在加載時(shí)修改屬性的值:
public boolean onLoad(Object arg0, Serializable arg1, Object[] arg2, 
    String[] arg3, Type[] arg4) throws CallbackException { 
     
  if (arg0 instanceof User) { 
    System.out.println("User to be loaded=>"+(arg2[0]+":"+arg2[1])); 
  } 
  User user = (User)arg0; 
  //判斷哪個(gè)屬性是name 
  for (int i = 0; i < arg3.length; i ++){ 
    if (arg3[i].equals("name")){ 
      user.setName(((String)arg2[i]).replace("123","")); 
      arg2[i] = ((String)arg2[i]).replace("123",""); 
    } 
  } 
  return false; 
} 

加載時(shí)修改屬性的值是寫在onLoad方法內(nèi)。
 這里的arg0就是我們的User對(duì)象,這里它還沒有值,這個(gè)方法在load方法之后才進(jìn)行調(diào)用,所以我們此時(shí)對(duì)user進(jìn)行操作已經(jīng)是于事無補(bǔ)了,而且我們這里的user.setName是沒用的操作。主要在:

arg2[i] = ((String)arg2[i]).replace("123","");

  
   這句代碼改變了返回的屬性的值,那么我們?cè)诔绦蛑心玫降膗ser對(duì)象中的值也會(huì)改變,我們運(yùn)行測試方法看看:

public static void main(String[] args) { 
 
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Interceptor interceptor = new MyInteceptor(); 
  Session session = sessionFactory.openSession(interceptor); 
     
  User user = (User)session.load(User.class,new Long(39)); 
     
  System.out.println("User name:"+user.getName()); 
  session.close(); 
     
} 

  看結(jié)果,我們得到了:

Hibernate: select user0_.USER_ID as USER1_0_0_, user0_.USER_NAME as USER2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_.USER_ID=? 
User to be loaded=>123shun:0 
User name:shun 

  我們已經(jīng)把原來的123給去掉了,在真正加載后進(jìn)行了相關(guān)的處理,不過這個(gè)并不是真正加載前的處理,有點(diǎn)投機(jī)的嫌疑。但也不失為一個(gè)考慮的方案。Interceptor也許用得最多的還是在日志的相關(guān)處理上,比如我們需要對(duì)每次操作都進(jìn)行相應(yīng)的日志記錄,那么Interceptor是一個(gè)很好的選擇。

Collection
記得我們?cè)谝郧袄又幸粚?duì)多中用到的Set,還有印象么,如果沒有趕快去查一下資料,回顧一下。今天我們就圍繞著這些Collection來進(jìn)行學(xué)習(xí)。
 還是不廢話了,我們直接進(jìn)入正題。
 1)首先我們來學(xué)習(xí)一下Set。大家都知道JAVA util包里面也有一個(gè)Set,那么hibernate里面的set和java的set和什么區(qū)別和聯(lián)系呢?我們打開hibernate的API,找到Set,可以看到。

詳解Java的Hibernate框架中的Interceptor和Collection

我們看到的就是這樣一個(gè)hibernate的集合的父類,它是一個(gè)抽象類,有一系列具體的實(shí)現(xiàn)類,我們繼續(xù)看到下面的方法時(shí),發(fā)現(xiàn)這個(gè)類實(shí)現(xiàn)上是對(duì)java集合的封裝,這樣我們就明白啦,所謂的hibernate的Set實(shí)際上也只是封裝了java的Set。
 那么,Set中不允許重復(fù)元素的這個(gè)特點(diǎn)是否也在hibernate中呢?答案當(dāng)然是肯定啦。
 我們這里不看這些,我們以前在學(xué)習(xí)映射時(shí)是直接把屬性和所關(guān)聯(lián)的類進(jìn)行關(guān)聯(lián),但今天我們不這樣啦,我們用另外一種方法,只是關(guān)聯(lián)一個(gè)字符串,看看有什么問題。
 但在看這個(gè)問題前,我們先來看看,java中的String比較。
我們看到的就是這樣一個(gè)hibernate的集合的父類,它是一個(gè)抽象類,有一系列具體的實(shí)現(xiàn)類,我們繼續(xù)看到下面的方法時(shí),發(fā)現(xiàn)這個(gè)類實(shí)現(xiàn)上是對(duì)java集合的封裝,這樣我們就明白啦,所謂的hibernate的Set實(shí)際上也只是封裝了java的Set。
 那么,Set中不允許重復(fù)元素的這個(gè)特點(diǎn)是否也在hibernate中呢?答案當(dāng)然是肯定啦。
 我們這里不看這些,我們以前在學(xué)習(xí)映射時(shí)是直接把屬性和所關(guān)聯(lián)的類進(jìn)行關(guān)聯(lián),但今天我們不這樣啦,我們用另外一種方法,只是關(guān)聯(lián)一個(gè)字符串,看看有什么問題。
 但在看這個(gè)問題前,我們先來看看,java中的String比較。

public static void main(String[] args) { 
 
  String s1 = "shun1"; 
  String s2 = "shun1"; 
  System.out.println("s1==s2:"+(s1==s2)); 
     
} 

    相信很多童鞋都知道答案是true。
在進(jìn)行例子前先看一下我們的映射文件,映射類那些就不寫了:
 這是TUser的映射文件:

<class name="TUser" table="t_user" dynamic-insert="true" dynamic-update="true"> 
  <id name="id" column="id"> 
    <generator class="native" /> 
  </id> 
  <property name="name" type="java.lang.String" column="name"/> 
  <property name="age" type="java.lang.Integer" column="age"/> 
  <set name="addresses" cascade="all" table="t_address"> 
    <key column="user_id" /> 
    <!-- <one-to-many class="Address"/> --> 
    <element column="address" type="string" /> 
  </set> 
   
</class> 

  接下來是Address的映射文件:

<class name="Address" table="t_address" dynamic-insert="false" dynamic-update="false"> 
  <id name="id" column="id" type="java.lang.Integer"> 
    <generator class="native" /> 
  </id> 
  <property name="address" column="address" type="java.lang.String" /> 
  <many-to-one name="user" class="TUser"  
    column="user_id" not-null="true"></many-to-one> 
 
</class> 

  童鞋們看清楚了,我在TUser中的Set里面把one-to-many注釋了而用了element,這里先不管它有什么問題,我們先看數(shù)據(jù)庫:
 這是t_address表:

詳解Java的Hibernate框架中的Interceptor和Collection

下面是t_user表:

詳解Java的Hibernate框架中的Interceptor和Collection

我們可以看到id為4的User對(duì)應(yīng)了三個(gè)地址,接下來,我們來看一下測試方法:

public static void main(String[] args) { 
     
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
     
  TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
  Set set = user.getAddresses(); 
  session.close();   
  System.out.println("address size:"+set.size()); 
} 

    很簡單的一個(gè)查詢類,只是取出了這個(gè)結(jié)果而已,我們看到一個(gè)奇怪的現(xiàn)象:

address size:1 

  這是結(jié)果!
 你肯定會(huì)說,肯定錯(cuò)了吧,是hibernate的bug。這里肯定高興啦,總算可以提交一個(gè)bug了,以前跳槽的時(shí)候可以大聲說我為hibernate提交過bug。哈哈,但很遺憾,這并不是bug。
 剛才說了我們前面的那個(gè)字符串比較的是為這里作鋪墊的,那么怎么鋪呢?
 我們?cè)谂渲梦募杏肧et,并且是通過String字符來進(jìn)行關(guān)聯(lián)的,那么它首先在數(shù)據(jù)庫中取出放進(jìn)Set中的時(shí)候會(huì)先判斷該關(guān)聯(lián)字符的值是否是相等的,這里由于我們的值都是相等的(這里我們暫時(shí)不深究它是怎么進(jìn)行比較的),我們只需要知道當(dāng)我們用字符串來進(jìn)行比較的時(shí)候,我們又陷入了JAVA中的字符串陷阱了。查出來只有一條,那么刪除呢,刪除的時(shí)候就比較麻煩啦,它會(huì)把所有相同的記錄都刪除。
 那么我們來看一下刪除的:

TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
     
Transaction tx = session.beginTransaction(); 
Object obj = user.getAddresses().iterator().next(); 
     
user.getAddresses().remove(obj); 
     
tx.commit(); 
session.close(); 

  這里hibernate輸出的語句是:

Hibernate: delete from t_address where user_id=? 

  相信什么時(shí)候大家都知道了,是刪除該用戶下的所有地址。這沒得選擇,只能全部都刪除。
 所以在真正的開發(fā)中需要注意。
 
 2)上面我們講了Set,好像用著不怎么爽啊,有那么個(gè)陷阱,但沒辦法,Set是我們用得最多的,而且一般也不會(huì)有人直接去關(guān)聯(lián)字符串吧。但很多人還是會(huì)不爽,那么hibernate也就應(yīng)大家要求搞多了一個(gè)Bag(也許不是應(yīng)要求,可能它們里面也有人不滿,哈哈)。
 我們先來看看它的基本用法:
 首先我們需要把前面的TUser的映射文件中的Set標(biāo)簽修改為:

<bag name="addresses" lazy="true" table="t_address"> 
  <key column="user_id" /> 
  <element type="string" column="address" /> 
</bag> 

  并且相應(yīng)的實(shí)體類需要把a(bǔ)ddresses的類型修改為List類型。
 這里我們重新添加三個(gè)地址:

詳解Java的Hibernate框架中的Interceptor和Collection

我們運(yùn)行測試代碼:

public static void main(String[] args) { 
   
  Configuration cfg = new Configuration().configure(); 
  SessionFactory sessionFactory = cfg.buildSessionFactory(); 
  Session session = sessionFactory.openSession(); 
     
  TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
     
  System.out.println("address size:"+user.getAddresses().size()); 
  session.close(); 
} 

 
   這里我們看到了:

address size:3 

  這次我們已經(jīng)全部都可以看到了,不管有沒有重復(fù)。
 
 但我們剛才看了一個(gè)刪除的問題,Bag在這里還是沒有解決,需要借助idBag。我們看到配置文件,需要如下的修改:

idbag name="addresses" table="t_address" lazy="true"> 
  <collection-id type="int" column="id"> 
    <generator class="identity" /> 
  </collection-id> 
  <key column="user_id" /> 
  <element type="string" column="address" /> 
</idbag> 

  我們看到它只比bag多了一個(gè)collection-id進(jìn)行表明要?jiǎng)h除的記錄號(hào)。
 當(dāng)我們重新運(yùn)行刪除的代碼:

TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
   
Transaction tx = session.beginTransaction(); 
Object obj = user.getAddresses().iterator().next(); 
user.getAddresses().remove(obj); 
     
tx.commit(); 

  我們看到輸出語句為:

Hibernate: delete from t_address where id=? 

  這次并不是通過user_id來進(jìn)行刪除,而是根據(jù)t_address的ID來進(jìn)行刪除,這說明它真正刪除我們需要?jiǎng)h除的那條記錄。
 我們看到數(shù)據(jù)庫,現(xiàn)在記錄是:

詳解Java的Hibernate框架中的Interceptor和Collection

我們已經(jīng)把第一條記錄給刪了,正確了。
 
 3)看了上面兩種方法,我們?cè)賮砜匆幌翸AP,它跟上面兩個(gè)最大的不同就是可以進(jìn)行鍵值的對(duì)應(yīng)。直接看代碼,直觀點(diǎn):
 首先,我們需要修改配置文件:

<map name="addresses" table="t_address" lazy="true"> 
  <key column="user_id" /> 
  <index type="string" column="type" /> 
  <element type="string" column="address" /> 
</map> 

  它和前面兩個(gè)最大的不同就是有一個(gè)index,這相當(dāng)于我們?cè)趈ava中map的key,我們通過這個(gè)來取出相對(duì)應(yīng)的記錄。記住,改完這里還要改相應(yīng)的實(shí)體類,需要把a(bǔ)ddresses屬性的類型改成Map。
 看看數(shù)據(jù)庫的數(shù)據(jù):

詳解Java的Hibernate框架中的Interceptor和Collection

這里我們看到有兩個(gè)office和一個(gè)home,那么office是拿哪個(gè)呢?
 不要急,我們運(yùn)行一下測試代碼就知道了:

TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
   
System.out.println(user.getAddresses().get("home")); 
System.out.println(user.getAddresses().get("office")); 
ShanWei 
ShangHai 

  對(duì),如結(jié)果可知,我們?nèi)〉玫氖呛竺婺莻€(gè),這跟Map的原理一樣,后面存入的值會(huì)覆蓋前面的值(如果它們是同一個(gè)key的情況下)。
 Map是比較簡單的,相當(dāng)前兩個(gè)來說。
 
 4)最后一個(gè)我們來看一下List。List與前幾種又有不同,不同在它可以進(jìn)行排序。
 我們來看一下它是怎么實(shí)現(xiàn)的:
 首先我們還是修改一下映射文件:

<list name="addresses" table="t_address" lazy="true"> 
  <key column="user_id" /> 
  <index type="string" column="idx" /> 
  <element type="string" column="address" /> 
</list> 

  它和Map的配置差不多,但index的屬性是不一樣的,Map中的index是作為key來取得值,而List的index是作為排序的。
 我們看數(shù)據(jù)庫:

詳解Java的Hibernate框架中的Interceptor和Collection

我們?cè)O(shè)了三個(gè)值,順序分別為0,1,2。
 下面我們運(yùn)行代碼來更改0,2的值:

TUser user = (TUser)session.load(TUser.class,new Integer(4)); 
   
Transaction tx = session.beginTransaction(); 
Object obj1 = user.getAddresses().get(0); 
Object obj2 = user.getAddresses().get(2); 
     
user.getAddresses().set(0,obj2); 
user.getAddresses().set(2,obj1); 
     
tx.commit(); 

   我們看到結(jié)果:

詳解Java的Hibernate框架中的Interceptor和Collection

我們看到,0,2已經(jīng)調(diào)換了,當(dāng)然這也只是調(diào)換了idx的值。但這已經(jīng)基本上實(shí)現(xiàn)了排序的功能了。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品www | 久久精品探花 | 国产一级aa大片毛片 | 成人免费一区二区 | 欧美人与性禽动交精品 | 一区二区精品视频 | 久久精品国产清自在天天线 | 国产日韩在线观看一区 | 久久精品国产99国产精品亚洲 | 欧美日韩大片在线观看 | 欧美一区二区网站 | 在线观看日本中文字幕 | 亚洲第一精品在线 | 国产宾馆3p国语对白 | 国产成人高清在线观看 | 日日操夜夜操视频 | 日夜操天天干 | 91久久线看在观草草青青 | 亚洲一区二区三区在线免费观看 | 日韩在线播放第一页 | 久久亚洲精选 | 久久精品无码一区二区三区 | 国产高清美女一级毛片久久 | 国产精品久久久久久久久久久久久久久久 | 毛片大全 | 成人资源在线观看 | chinese 军人 gay xx 呻吟 | 在线天堂中文在线资源网 | 欧美扩阴视频 | 国产大片全部免费看 | 天堂福利电影 | 爱性久久久久久久 | 欧美一级黄色影院 | 国产 日韩 亚洲 欧美 | 日韩在线播放第一页 | 黄色片在线观看网站 | 视频一区二区三区在线播放 | 欧美日韩在线播放 | 欧美成人久久 | 久久久裸体视频 | 双性精h调教灌尿打屁股的文案 |