一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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

服務(wù)器之家 - 編程語言 - JAVA教程 - 簡(jiǎn)要分析Java的Hibernate框架中的自定義類型

簡(jiǎn)要分析Java的Hibernate框架中的自定義類型

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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() 方法,這個(gè)方法主要用到把此類型的值保存到數(shù)據(jù)庫,這一次我們先學(xué)怎么用,以后我們?cè)俾芯績(jī)?nèi)部是怎么來實(shí)現(xiàn)的。
 2)我學(xué)習(xí)時(shí)寫的例子是參照夏昕的例子,所以肯定和網(wǎng)上的大部分都一樣,我們只是大概分析一下:
 下面是User類

?
1
2
3
4
5
6
7
8
9
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類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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í)不用的方法則沒有寫出來,但還是需要實(shí)現(xiàn)的。
 3)接下來就是User類的映射文件:

?
1
2
3
4
5
6
7
<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)最后我們來寫一個(gè)測(cè)試類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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();
  }
}

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

簡(jiǎn)要分析Java的Hibernate框架中的自定義類型

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

?
1
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方法時(shí)變成了List的List,即
value:[[[email protected], [email protected]]]這樣的形式,這樣在比較的時(shí)候就會(huì)出問題,它永遠(yuǎn)都只有一個(gè)值,而在比較的時(shí)候卻是不同的,

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

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

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无人区在线观看免费国语完整版 | 日本一区二区三区在线 观看网站 | 日韩中文字幕一区 | 成人性爱视频在线观看 | 99久久精品6在线播放 | 久久视频这只精品99re6 | 国产精视频| 蜜色影院 | 欧美brazzers| 九九国产视频 | 久久久久青草大香线综合精品 | 鬼惨笑小说 | 特黄特级高清免费视频毛片 | 国产毛片在线观看 | 天堂中文在线免费观看 | 久久中文电影 | 国产精品微拍 | 任我行视频在线观看国语 | 无人区在线观看免费视频国语 | 色婷婷综合久久久中文字幕 | 国产精品天天看特色大片不卡 | 波多野结衣无码 | 美女脱一光二净的视频 | 四虎国产成人亚洲精品 | 99国产精品热久久久久久夜夜嗨 | 毛片大全免费看 | 女人张开腿让男人做爽爽 | 日产乱码卡1卡2卡三卡四在线 | 欧洲肥女大肥臀 | 日本亚洲娇小与黑人tube | 日韩精品免费一区二区三区 | 91久久国产成人免费观看资源 | 欧美精品一区二区三区免费观看 | 国产一级片免费视频 | 欧美一区二区三区精品国产 | 国产精品青青在线观看香蕉 | 乌克兰xxxxx| 无遮掩60分钟从头啪到尾 | 9999热视频| 91香蕉国产视频 | 美女任你摸 |