2009年8月7日 星期五

Hibernate實作UserType之例子

說明:由於Hibernate並沒有提供特殊的原生類別當作Mapping欄位(如我們需要List集合之類別),故Hibernate提供一個UserType Interface讓我們自己實作一個UserType。

實作方法如下:1.於t_user表格中加入一個email欄位,此email儲存資料的方式是以分號";"加以分隔,t_user表格schema如下:

drop table if exists t_user;
create table t_user(
id int(11) auto_increment,
name varchar(50) not null default '',
age int(3),
version int(4),
email varchar(300),
primary key (id));

2.建立一個EMailList類別實作UserType Interface,類別內容如下:
package org.redsaga.usertype;
import java.util.List;
import java.util.ArrayList;
import java.io.Serializable;
import java.sql.Types;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public class EMailList implements Serializable,UserType {
private static final char SPLITTER=';';
private static final int[] TYPES = new int[]{Types.VARCHAR};
public boolean isMutable(){
return false;
}
public int[] sqlTypes(){
return TYPES;
}
public Class returnedClass(){
return List.class;
}
/**
* 建立一個新的List實例,包含原有List實例中的所有元素
*/
public Object deepCopy(Object value)throws HibernateException{
List sourceList = (List)value;
List targetList = new ArrayList();
targetList.addAll(sourceList);
return targetList;
}
/**
* 判斷email list是否發生改變
*/
public boolean equals(Object x,Object y)throws HibernateException{
if(x==y){
return true;
}
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;
}else{
return false;
}
}
/**
* 將以";"分隔的字串解析為一個字串陣例
*
* @param value
* @return List
*/
public List parse(String value){
String[] strs = org.apache.commons.lang.StringUtils.split(value, SPLITTER);
List emailList = new ArrayList();
for(int i=0;i<strs.length;i++){
emailList.add(strs[i]);
}
return emailList;
}
/**
* 將String拼裝為一個字串,以";"分隔巷
*/
public String assemble(List emailList){
StringBuffer strBuf = new StringBuffer();
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();
}
/**
* 從ResultSet中取出email欄位,並將其解析為List類型後回傳
*/
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)throws HibernateException,SQLException{
System.out.println("nullSafeGet method executed");
String value = (String)Hibernate.STRING.nullSafeGet(rs, names[0]);
if(value!=null){
return parse(value);
}else{
return null;
}
}
/**
* 將List型的email資訊組裝成字串之後保存到email欄位
*/
public void nullSafeSet(PreparedStatement st, Object value, int index)throws HibernateException,SQLException{
System.out.println("nullSafeSet method executed");
if(value!=null){
String str = assemble((List)value);
Hibernate.STRING.nullSafeSet(st, str, index);
}else{
Hibernate.STRING.nullSafeSet(st, value, index);
}
}
public Object assemble(Serializable cached, Object owner)throws HibernateException{
return null;
}
public Serializable disassemble(Object value)throws HibernateException{
return null;
}
public int hashCode(Object x)throws HibernateException{
return 0;
}
public Object replace(Object original, Object target, Object owner)throws HibernateException{
return null;
}
}
=======================================
3.TUser.java及TUser.hbm.xml內容如下
package org.redsaga.quickstart;
// Generated 2009/8/6 下午 11:08:15 by Hibernate Tools 3.2.4.GA
import java.util.List;
/**
* TUser generated by hbm2java
*/
public class TUser implements java.io.Serializable {
private Integer id;
private Integer version;
private String name;
private Integer age;
private List email;
public TUser() {
}
public TUser(String name) {
this.name = name;
}
public TUser(String name, Integer age, List email) {
this.name = name;
this.age = age;
this.email = email;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public List getEmail() {
return this.email;
}
public void setEmail(List email) {
this.email = email;
}
}
=========================================
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2009/8/6 ?U?? 11:08:15 by Hibernate Tools 3.2.4.GA -->
<hibernate-mapping>
<class name="org.redsaga.quickstart.TUser" table="t_user" catalog="manning">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<version name="version" type="java.lang.Integer">
<column name="version" />
</version>
<property name="name" type="string">
<column name="name" length="50" not-null="true" />
</property>
<property name="age" type="java.lang.Integer">
<column name="age" />
</property>
<property name="email" type="org.redsaga.usertype.EMailList">
<column name="email" length="300" />
</property>
</class>
</hibernate-mapping>
==========================================
4.Hibernate.cfg.xml,內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.password">action</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/manning</property>
<property name="hibernate.connection.username">manning</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 將SQL輸出到Console -->
<property name="hibernate.show_sql">true</property>
<!-- 使用JDBC Transaction -->
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<!-- 將TUser.hbm.xml加到Hibernate.cfg.xml檔案中 -->
<mapping resource="org/redsaga/quickstart/TUser.hbm.xml"/>
</session-factory>
</hibernate-configuration>
======================================
5.利用JUnit建立一個測試method(testUserType),內容如下:
/** * testUserType 測試UserType for email欄位是否有效 * @throws Exception */ public void testUserType() throws Exception { TUser user=null; Transaction tran = null; String hql = " from TUser where name='Emma'"; try{ tran = session.beginTransaction(); List emailList = new ArrayList(); user = new TUser(); user.setName("Emma"); user.setAge(19); emailList.add("Emma@org.redsaga"); emailList.add("Emma@yahoo.com.tw"); user.setEmail(emailList); session.save(user); session.flush(); tran.commit(); List userList = session.createQuery(hql).list(); //添加一個Email後保存 for(int i=0;i<userList.size();i++){ user = (TUser)userList.get(i); System.out.println(user.getEmail()); } }catch(HibernateException e){ e.printStackTrace(); } }
==========================================
6.測試結果:
Mysql查詢結果:
console輸出結果
Hibernate: insert into manning.t_user (version, name, age, email) values (?, ?, ?, ?)
nullSafeSet method executed
Hibernate: select tuser0_.id as id0_, tuser0_.version as version0_, tuser0_.name as name0_, tuser0_.age as age0_, tuser0_.email as email0_ from manning.t_user tuser0_ where tuser0_.name='Emma'
[Emma@org.redsaga, Emma@yahoo.com.tw]

沒有留言:

張貼留言