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

簡要分析Java的Hibernate框架中的自定義類型

 更新時間:2016年01月03日 17:32:47   作者:cxshun  
這篇文章主要介紹了Java的Hibernate框架中的自定義類型,Hibernate是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下

最近看到hibernate的自定義類型,這個以前沒接觸過,在這里記錄一下,當(dāng)是對自己知識的鞏固,也讓沒有接觸過的朋友一起學(xué)習(xí)研究一番。
 1)自定義類型,顧名思義,當(dāng)然就是由于內(nèi)部的類型不滿足需求,而自己來進(jìn)行實(shí)現(xiàn)的類型。這種情況不多,但我們還是有必要學(xué)習(xí)一下,技多不壓身嘛。也學(xué)習(xí)一下,別人在做框架的時候是怎么去考慮的,怎么去思考擴(kuò)展性的。
 自定義類型有兩個方法來實(shí)現(xiàn),一種是實(shí)現(xiàn)UserType,另外一種實(shí)現(xiàn)CompositeUserType,另外可能還有一些方法,但我暫時沒用到,先不講了。
 我暫時只用到UserType,我們就先看一下UserType接口的定義:

public interface UserType { 
  /** 
   * Return the SQL type codes for the columns mapped by this type. The 
   * codes are defined on <tt>java.sql.Types</tt>. 
   */ 
  public int[] sqlTypes(); 
 
  /** 
   * The class returned by <tt>nullSafeGet()</tt>. 
   */ 
  public Class returnedClass(); 
 
  /** 
   * Compare two instances of the class mapped by this type for persistence "equality". 
   * Equality of the persistent state. 
   */ 
  public boolean equals(Object x, Object y) throws HibernateException; 
 
  /** 
   * Get a hashcode for the instance, consistent with persistence "equality" 
   */ 
  public int hashCode(Object x) throws HibernateException; 
 
  /** 
   * Retrieve an instance of the mapped class from a JDBC resultset. Implementors 
   * should handle possibility of null values. 
   */ 
  public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException; 
 
  /** 
   * Write an instance of the mapped class to a prepared statement. Implementors 
   * should handle possibility of null values. A multi-column type should be written 
   * to parameters starting from <tt>index</tt>. 
   */ 
  public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException; 
 
  /** 
   * Return a deep copy of the persistent state, stopping at entities and at 
   * collections. It is not necessary to copy immutable objects, or null 
   * values, in which case it is safe to simply return the argument. 
   */ 
  public Object deepCopy(Object value) throws HibernateException; 
 
  /** 
   * Are objects of this type mutable? 
   * 
   * @return boolean 
   */ 
  public boolean isMutable(); 
 
  /** 
   * Transform the object into its cacheable representation. At the very least this 
   * method should perform a deep copy if the type is mutable. That may not be enough 
   * for some implementations, however; for example, associations must be cached as 
   * identifier values. (optional operation) 
   * 
   * @param value the object to be cached 
   * @return a cachable representation of the object 
   * @throws HibernateException 
   */ 
  public Serializable disassemble(Object value) throws HibernateException; 
 
  /** 
   * Reconstruct an object from the cacheable representation. At the very least this 
   * method should perform a deep copy if the type is mutable. (optional operation) 
   */ 
  public Object assemble(Serializable cached, Object owner) throws HibernateException; 
 
  /** 
   * During merge, replace the existing (target) value in the entity we are merging to 
   * with a new (original) value from the detached entity we are merging. For immutable 
   * objects, or null values, it is safe to simply return the first parameter. For 
   * mutable objects, it is safe to return a copy of the first parameter. For objects 
   * with component values, it might make sense to recursively replace component values. 
   */ 
  public Object replace(Object original, Object target, Object owner) throws HibernateException; 
} 

  其實(shí)大家看英文一般情況下都能理解,不再多做解釋了,這里我們最主要的就是實(shí)現(xiàn)nullSafeSet() 方法,這個方法主要用到把此類型的值保存到數(shù)據(jù)庫,這一次我們先學(xué)怎么用,以后我們再慢慢研究內(nèi)部是怎么來實(shí)現(xiàn)的。
 2)我學(xué)習(xí)時寫的例子是參照夏昕的例子,所以肯定和網(wǎng)上的大部分都一樣,我們只是大概分析一下:
 下面是User類

package org.hibernate.tutorial.domain; 
import java.io.Serializable; 
import java.util.List; 
public class User implements Serializable{ 
  public Long id; 
  private String name; 
  private List emails; 
    省略Get/Set方法 
} 

  下來是自定義的EmailList類:

package org.hibernate.tutorial.domain; 
import java.io.Serializable; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.util.ArrayList; 
import java.util.List; 
import org.hibernate.Hibernate; 
import org.hibernate.HibernateException; 
import org.hibernate.usertype.UserType; 
 
public class EmailList implements UserType { 
 
  private static final char SPLITTER = ';'; 
  private static final int[] TYPES = new int[] {Types.VARCHAR}; 
   
  private String assemble(List emailList) { 
    StringBuilder strBuf = new StringBuilder(); 
    for (int i = 0; i < emailList.size() - 1; i++){ 
      strBuf.append(emailList.get(i)).append(SPLITTER); 
    } 
    strBuf.append(emailList.get(emailList.size()-1)); 
    return strBuf.toString(); 
  } 
   
  private List parse(String value) { 
    String[] strs = org.hibernate.util.StringHelper.split(value,String.valueOf(SPLITTER)); 
    List emailList = new ArrayList(); 
    for (int i = 0;i < strs.length; i++) { 
      emailList.add(strs[i]); 
    } 
    return emailList; 
  } 
 
  public Object deepCopy(Object value) throws HibernateException { 
    List sourceList = (List)value; 
    List targetList = new ArrayList(); 
    targetList.add(sourceList); 
    return targetList; 
  } 
 
  public Serializable disassemble(Object value) throws HibernateException { 
    return null; 
  } 
 
  public boolean equals(Object x, Object y) throws HibernateException { 
    if (x == y) return true; 
     
    System.out.println("X:"+x+"Y:"+y); 
     
    if (x != null && y != null) { 
      List xList = (List)x; 
      List yList = (List)y; 
       
      if(xList.size() != yList.size()) return false; 
       
      for (int i = 0; i < xList.size(); i++) { 
        String str1 = (String)xList.get(i); 
        String str2 = (String)yList.get(i); 
         
        if (!str1.equals(str2)) return false; 
      } 
       
      return true; 
    } 
     
    return false; 
  } 
 
  public boolean isMutable() { 
    return false; 
  } 
 
  public Object nullSafeGet(ResultSet rs, String[] names, Object owner) 
      throws HibernateException, SQLException { 
    String value = (String)Hibernate.STRING.nullSafeGet(rs, names[0]); 
    if (value != null) { 
      return parse(value);//把List通過;分割 
    } else{ 
      return null; 
    } 
  } 
 
  public void nullSafeSet(PreparedStatement st, Object value, int index) 
      throws HibernateException, SQLException { 
    System.out.println("Set Method Executed!"); 
     
    System.out.println("value:" + value); 
     
    if (value != null){ 
      String str = assemble((List)value);//把字符串用;拼接 
       
      Hibernate.STRING.nullSafeSet(st, str, index); 
    } else { 
      Hibernate.STRING.nullSafeSet(st, value, index); 
    } 
  } 
 
  public Class returnedClass() { 
    return List.class; 
  } 
 
  public int[] sqlTypes() { 
    return TYPES; 
  } 
  //省略其他不需要修改的方法 
} 

  類中實(shí)現(xiàn)的方法是需要修改的方法,其他不需要修改暫時不用的方法則沒有寫出來,但還是需要實(shí)現(xiàn)的。
 3)接下來就是User類的映射文件:

<class name="User" table="USER"> 
    <id name="id" column="USER_ID" type="java.lang.Long"> 
      <generator class="native" /> 
    </id> 
    <property name="name" type="string" column="USER_NAME"/> 
    <property name="emails" type="org.hibernate.tutorial.domain.EmailList" column="emails"/> 
  </class> 

  相信大家都知道怎么進(jìn)行修改,這里也不進(jìn)行講解了,主要是修改emails的type,修改為我們剛才定義的EmailList類。
 4)最后我們來寫一個測試類:

import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.ArrayList; 
import junit.framework.TestCase; 
 
import org.hibernate.EntityMode; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.tutorial.domain.User; 
 
public class HibernateTest extends TestCase{ 
 
  private Session session = null; 
   
  protected void setUp() throws Exception { 
     
    Configuration cfg = new Configuration().configure(); 
    SessionFactory sessionFactory = cfg.buildSessionFactory(); 
     
    session = sessionFactory.openSession(); 
 
  } 
   
  public void testInsert(){ 
    Transaction tran = null; 
    try{ 
      tran = session.beginTransaction(); 
       
      User user = new User(); 
       
      user.setName("shun"); 
       
      List list = new ArrayList(); 
       
      list.add("12312@sfsdf.com"); 
      list.add("123@123.com"); 
 
      user.setEmails(list); 
      session.save(user); 
       
      tran.commit(); 
    } catch (Exception ex) { 
      ex.printStackTrace(); 
      if (tran != null){ 
        tran.rollback(); 
      } 
    } 
  } 
   
  protected void tearDown() throws Exception { 
    session.close(); 
  } 
} 

  這里可能會出現(xiàn)問題,當(dāng)我們只保存一個email時,它會出現(xiàn)異常,在數(shù)據(jù)庫里面是email字段是空的,而當(dāng)我們?nèi)缟厦娲a一樣,有兩個時,并不會出現(xiàn)問題,數(shù)據(jù)庫中結(jié)果如圖:

201613173332381.png (535×20)

而當(dāng)我們只保存一個時,異常如下:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String 

 它發(fā)生在EmailList的equals方法中的String str1 = (String)xList.get(i);這句代碼中,經(jīng)檢查是在插入數(shù)據(jù)傳到EmailList的nullSafeSet方法時變成了List的List,即
value:[[12312@sfsdf.com, 123@123.com]]這樣的形式,這樣在比較的時候就會出問題,它永遠(yuǎn)都只有一個值,而在比較的時候卻是不同的,

if(xList.size() != yList.size()) return false; 

 所以在強(qiáng)制轉(zhuǎn)換時會出問題。
 而經(jīng)過檢查,equals方法里:
 

X:[[12312@sfsdf.com, 123@123.com]]Y:[12312@sfsdf.com, 123@123.com] 

 這樣的結(jié)果卻是很奇怪的。網(wǎng)上并沒有講到為什么會出現(xiàn)這種情況。這里提出一下:我用的hibernate版本是Hibernate 3.3.2.GA。不知道是版本問題還是其他問題,我們明天再研究一下。如果有哪位兄弟知道為什么的,希望也不吝告訴我一下。

相關(guān)文章

  • Java編程實(shí)現(xiàn)swing圓形按鈕實(shí)例代碼

    Java編程實(shí)現(xiàn)swing圓形按鈕實(shí)例代碼

    這篇文章主要介紹了Java編程實(shí)現(xiàn)swing圓形按鈕實(shí)例代碼,涉及兩個簡單的Java實(shí)現(xiàn)按鈕的代碼,其中一個具有偵測點(diǎn)擊事件的簡單功能,具有一定借鑒價(jià)值,需要的朋友可以參考。
    2017-11-11
  • java獲取客服端信息的方法(系統(tǒng),瀏覽器等)

    java獲取客服端信息的方法(系統(tǒng),瀏覽器等)

    下面小編就為大家?guī)硪黄猨ava獲取客服端信息的方法(系統(tǒng),瀏覽器等)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • 基于MyBatis的parameterType傳入?yún)?shù)類型

    基于MyBatis的parameterType傳入?yún)?shù)類型

    這篇文章主要介紹了基于MyBatis的parameterType傳入?yún)?shù)類型,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • JAVA垃圾收集器與內(nèi)存分配策略詳解

    JAVA垃圾收集器與內(nèi)存分配策略詳解

    這篇文章介紹了JAVA垃圾收集器與內(nèi)存分配策略,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2015-07-07
  • MyBatis的foreach語句詳解

    MyBatis的foreach語句詳解

    這篇文章主要介紹了MyBatis的foreach語句詳解的相關(guān)資料,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • Java8處理List的雙層循環(huán)問題

    Java8處理List的雙層循環(huán)問題

    這篇文章主要介紹了Java8處理List的雙層循環(huán)問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • JAVA記住密碼功能的實(shí)現(xiàn)代碼

    JAVA記住密碼功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了JAVA記住密碼功能的實(shí)現(xiàn)代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-01-01
  • JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說

    JVM垃圾回收機(jī)制和垃圾回收器詳細(xì)解說

    這篇文章主要介紹了JVM垃圾回收機(jī)制和垃圾回收器,為了讓程序員更加專注于代碼的實(shí)現(xiàn),而不用過多的考慮內(nèi)存釋放的問題,所以在Java語言中,有了自動的垃圾回收機(jī)制,也是我們常常提及的GC,需要的朋友可以參考下
    2022-07-07
  • JVM中ClassLoader類加載器的深入理解

    JVM中ClassLoader類加載器的深入理解

    這篇文章主要給大家介紹了關(guān)于JVM中ClassLoader類加載器的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Springboot中攔截GET請求獲取請求參數(shù)驗(yàn)證合法性核心方法

    Springboot中攔截GET請求獲取請求參數(shù)驗(yàn)證合法性核心方法

    這篇文章主要介紹了Springboot中攔截GET請求獲取請求參數(shù)驗(yàn)證合法性,在Springboot中創(chuàng)建攔截器攔截所有GET類型請求,獲取請求參數(shù)驗(yàn)證內(nèi)容合法性防止SQL注入,這種方法適用攔截get類型請求,需要的朋友可以參考下
    2023-08-08

最新評論

安化县| 宝山区| 临朐县| 南通市| 北宁市| 利辛县| 崇仁县| 通州区| 土默特右旗| 三穗县| 武定县| 兰州市| 鄂温| 河东区| 北辰区| 北川| 尼勒克县| 石柱| 申扎县| 阿坝县| 方城县| 金坛市| 青铜峡市| 尼玛县| 衡南县| 扎兰屯市| 柏乡县| 武胜县| 泗阳县| 抚宁县| 富顺县| 武川县| 万州区| 阿拉善盟| 福泉市| 无锡市| 乐至县| 普兰店市| 泸西县| 奈曼旗| 嘉祥县|