国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

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

2019-11-26 14:42:06
字體:
來源:轉載
供稿:網友

最近看到hibernate的自定義類型,這個以前沒接觸過,在這里記錄一下,當是對自己知識的鞏固,也讓沒有接觸過的朋友一起學習研究一番。
 1)自定義類型,顧名思義,當然就是由于內部的類型不滿足需求,而自己來進行實現的類型。這種情況不多,但我們還是有必要學習一下,技多不壓身嘛。也學習一下,別人在做框架的時候是怎么去考慮的,怎么去思考擴展性的。
 自定義類型有兩個方法來實現,一種是實現UserType,另外一種實現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; } 

  其實大家看英文一般情況下都能理解,不再多做解釋了,這里我們最主要的就是實現nullSafeSet() 方法,這個方法主要用到把此類型的值保存到數據庫,這一次我們先學怎么用,以后我們再慢慢研究內部是怎么來實現的。
 2)我學習時寫的例子是參照夏昕的例子,所以肯定和網上的大部分都一樣,我們只是大概分析一下:
 下面是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;   }   //省略其他不需要修改的方法 } 

  類中實現的方法是需要修改的方法,其他不需要修改暫時不用的方法則沒有寫出來,但還是需要實現的。
 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> 

  相信大家都知道怎么進行修改,這里也不進行講解了,主要是修改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();   } } 

  這里可能會出現問題,當我們只保存一個email時,它會出現異常,在數據庫里面是email字段是空的,而當我們如上面代碼一樣,有兩個時,并不會出現問題,數據庫中結果如圖:

201613173332381.png (535×20)

而當我們只保存一個時,異常如下:

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

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

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

 所以在強制轉換時會出問題。
 而經過檢查,equals方法里:
 

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 萝北县| 辽宁省| 漳浦县| 彭水| 浦县| 天长市| 花垣县| 高陵县| 正蓝旗| 建昌县| 和顺县| 长宁县| 察隅县| 弥渡县| 耿马| 安塞县| 英山县| 梧州市| 义乌市| 运城市| 博罗县| 平度市| 元谋县| 吴川市| 吉木萨尔县| 德令哈市| 石泉县| 神木县| 鲁山县| 安徽省| 洪泽县| 亳州市| 岳普湖县| 安化县| 龙游县| 扬州市| 安塞县| 秀山| 通化县| 肇州县| 长汀县|