程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 扼要剖析Java的Hibernate框架中的自界說類型

扼要剖析Java的Hibernate框架中的自界說類型

編輯:關於JAVA

扼要剖析Java的Hibernate框架中的自界說類型。本站提示廣大學習愛好者:(扼要剖析Java的Hibernate框架中的自界說類型)文章只能為提供參考,不一定能成為您想要的結果。以下是扼要剖析Java的Hibernate框架中的自界說類型正文


比來看到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("[email protected]"); 
      list.add("[email protected]"); 
 
      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字段是空的,而當我們如下面代碼一樣,有兩個時,其實不會湧現成績,數據庫中成果如圖:

而當我們只保留一個時,異常以下:

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:[[[email protected], [email protected]]]如許的情勢,如許在比擬的時刻就會出成績,它永久都只要一個值,而在比擬的時刻倒是分歧的,

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

 所以在強迫轉換時會出成績。
 而經由檢討,equals辦法裡:
 

X:[[[email protected], [email protected]]]Y:[[email protected], [email protected]] 

 如許的成果倒是很奇異的。網上並沒有講到為何會湧現這類情形。這裡提出一下:我用的hibernate版本是Hibernate 3.3.2.GA。不曉得是版本成績照樣其他成績,我們今天再研討一下。假如有哪位兄弟曉得為何的,願望也不惜告知我一下。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved