介紹Hibernate使用UserType
Hibernate有很多值得學(xué)習(xí)的地方,這里我們主要介紹Hibernate使用UserType,包括介紹UserType就是用戶自定義類型等方面。
1、建立數(shù)據(jù)庫的時候***建立一個跟業(yè)務(wù)邏輯完全沒有關(guān)系的id,這樣的好處就是以后當(dāng)數(shù)據(jù)量大的時候可以容易的建立索引,而且當(dāng)業(yè)務(wù)邏輯變化的時候底層的數(shù)據(jù)結(jié)構(gòu)不用變化很大。
2、代碼的干凈是非常非常的重要的,從現(xiàn)在開始盡量讓自己的代碼寫的漂亮把!因為干凈的代碼不僅容易維護(hù),而且容易發(fā)現(xiàn)bug,在Hibernate使用UserType是很好用的。舉個經(jīng)典的例子:
實(shí)現(xiàn)Hibernate使用UserType接口的email 類
比如 你需要在 TUSER 表中記錄一個人的 email ,單獨(dú)為其建立一張數(shù)據(jù)庫表是很浪費(fèi)資源的,一般的方法是將TUSER 一欄 varchar 的來記錄email ,多個 email 之間用 " ; "號分開,我曾經(jīng)做的項目中采取的方法是:取出一個記錄著多條 email 的 string然后再來用 ; 號拆開,但是這樣子就有個不好,在一堆整齊的 get 方法用出來一個有 bad smell 的代碼。
有兩個方法,一個是修改映射TUSER的 java 類在其中增加一個 getEmail 方法,返回一個 list ,該方法對原先的 getEmail 方法進(jìn)行二次處理。第二個方法就是采用UserType 。
UserType就是用戶自定義類型,這里的類型指的是除了Hibernate定義的那些類型之外的用戶自己定義的。
一個實(shí)現(xiàn)Hibernate使用UserType接口的 email 類如下(里面的每個方法都是必須實(shí)現(xiàn)的接口方法,許多都可以復(fù)制粘貼的,不復(fù)雜):
- public class Email implements UserType
- ...{
- // 表示本類型實(shí)例是否可變,一般是不可變
- public boolean isMutable()
- ...{
- return false;
- }
- //該類型對應(yīng)的 sql 類型
- public int[] sqlTypes()
- ...{
- return new int[]......{Types.VARCHAR};
- }
- // 改類型對應(yīng)的 java 類型
- public Class returnedClass()
- ...{
- return List.class;
- }
- // 完全復(fù)制的方法,由于是用戶自己定義的類型
- //所以hibernate并不知道要如何來復(fù)制這個類,需要用戶自己定義
- public Object deepCopy(Object value)throws HibernateException
- ...{
- List source = (List)value;
- List target = new ArrayList();
- target.addAll(source);
- return target;
- }
- //equals方法,這個就不用多說了吧,肯定是要用戶自定義的
- public boolean equals(Object x,Object y) throws HibernateException
- ...{
- //這部分不寫出來了,自己實(shí)現(xiàn)吧,這個不是我要講的重點(diǎn)
- }
- /** *//**//*
- 這才是重頭戲!nullSafeGet 和nullSafeSet 是核心所在,對數(shù)據(jù)的后期處理都在這兩個方法里面
- nullSafeGet 是讀取的方法
- owner 目前沒用到過。
- names 是對應(yīng)的數(shù)據(jù)庫列名,UserType是可以對應(yīng)多個列的
- */
- public Object nullSafeGet(ResultSet rs,String[] names,Object owner)
throws HibernateException,SQLException- ...{
- String value = (String)Hibernate.STRING.nullSafeGet(rs,names[0]);
- if(value != null)
- ...{
- //把 string 拆開成 list 的代碼放在這里
- }
- return resultList;//得到了拆開的 郵件列表
- }
- /**//*
- 保存的方法
- index 是那個 PreparedStatement 的參數(shù)序號,一般來說不用管直接往下傳
- value 就是要保存的數(shù)據(jù),在這邊是一個保存著 email 列表的 List
- */
- public void nullSafeSet(PreparedStatement st,Object value,int index)
throws HibernateException,SQLException- ...{
- if(value != null)
- ...{
- String email = assemble(value);//將 List 拼合成 String 的 Email 的方法
- Hibernate.STRING.nullSafeSet(st,email,index);
- }
- else
- ...{
- Hibernate.STRING.nullSafeSet(st,value,index);
- }
- }
- }
在TUser.hbm.xml 中如此設(shè)置:
- <hibernate-mapping>
- <class name="entity.TUser" table="T_USER">
- </class>
- ..............
- <property name = "emali"column = "email"type = "mytype.Email"/>
- </hibernate-mapping>
在TUser.java中如此設(shè)置
- public class TUser implement Serializable
- ...{
- private Integer id;
- privarte Stirng name;
- //看,這邊的 email 可以大膽的使用 List 了
- private List email;
- //下面是一些 getter 和 setter 了
- }
這樣設(shè)置后你使用 TUser的時候要取出 email 直接 getEmail 出來的就是一個List 了,而且前臺根本不知道后臺干了什么,這樣代碼就簡潔多了。
【編輯推薦】