Hibernate映射自定義數據類型
數據庫中存在一個email字段,并允許其中存儲多個email地址,各地址之間使用 ; 分割,但是在POJO中,為了便于處理,email定義為一個List對象。
如何將String字段映射為List類型,Hibernate并沒有提供原生支持,需要我們實現自己的UserType。
1.數據庫定義
DROP
TABLE
t_user_mail;
CREATE TABLE t_user_mail (
id INT NOT NULL AUTO_INCREMENT
, name VARCHAR ( 50 )
, age INT
, email VARCHAR ( 300 )
, PRIMARY KEY (id)
);
CREATE TABLE t_user_mail (
id INT NOT NULL AUTO_INCREMENT
, name VARCHAR ( 50 )
, age INT
, email VARCHAR ( 300 )
, PRIMARY KEY (id)
);
2.
實現了UserType的自定義數據類型類EMailList
package
cn.blogjava.usertype;
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.apache.commons.lang.StringUtils;
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};
public int [] sqlTypes() {
// TODO Auto-generated method stub
return TYPES;
}
public Class returnedClass() {
// TODO Auto-generated method stub
return List. class ;
}
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 ;
}
return false ;
}
public int hashCode(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return 0 ;
}
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);
} else {
return null ;
}
}
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (value != null ) {
String str = assemble((List)value);
Hibernate.STRING.nullSafeSet(st, str, index);
} else {
Hibernate.STRING.nullSafeSet(st, value, index);
}
}
public Object deepCopy(Object value) throws HibernateException {
List sourceList = (List)value;
List targetList = new ArrayList();
targetList.addAll(sourceList);
return targetList;
}
public boolean isMutable() {
// TODO Auto-generated method stub
return false ;
}
public Serializable disassemble(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object assemble(Serializable arg0, Object arg1)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
private String assemble(List emailList) {
StringBuffer strBuf = new StringBuffer();
for ( int i = 0 ; i < emailList.size() - 1 ; i ++ ) {
strBuf.append((String)emailList.get(i)).append(SPLITTER);
}
strBuf.append(emailList.get(emailList.size() - 1 ));
return strBuf.toString();
}
private List parse(String value) {
String[] strs = StringUtils.split(value, SPLITTER);
List emailList = new ArrayList();
for ( int i = 0 ; i < strs.length; i ++ ) {
emailList.add(strs[i]);
}
return emailList;
}
}
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.apache.commons.lang.StringUtils;
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};
public int [] sqlTypes() {
// TODO Auto-generated method stub
return TYPES;
}
public Class returnedClass() {
// TODO Auto-generated method stub
return List. class ;
}
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 ;
}
return false ;
}
public int hashCode(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return 0 ;
}
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);
} else {
return null ;
}
}
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (value != null ) {
String str = assemble((List)value);
Hibernate.STRING.nullSafeSet(st, str, index);
} else {
Hibernate.STRING.nullSafeSet(st, value, index);
}
}
public Object deepCopy(Object value) throws HibernateException {
List sourceList = (List)value;
List targetList = new ArrayList();
targetList.addAll(sourceList);
return targetList;
}
public boolean isMutable() {
// TODO Auto-generated method stub
return false ;
}
public Serializable disassemble(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object assemble(Serializable arg0, Object arg1)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
private String assemble(List emailList) {
StringBuffer strBuf = new StringBuffer();
for ( int i = 0 ; i < emailList.size() - 1 ; i ++ ) {
strBuf.append((String)emailList.get(i)).append(SPLITTER);
}
strBuf.append(emailList.get(emailList.size() - 1 ));
return strBuf.toString();
}
private List parse(String value) {
String[] strs = StringUtils.split(value, SPLITTER);
List emailList = new ArrayList();
for ( int i = 0 ; i < strs.length; i ++ ) {
emailList.add(strs[i]);
}
return emailList;
}
}
3.
配置文件TUserMail.hbm.xml

























4.
在hibernate.cfg.xml載入TUserMail.hbm.xml
















5.
測試類HibernateTest.java
package cn.blogjava.usertype;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class HibernateTest extends TestCase {
Session session = null;
/**
* JUnit中的setUp方法在TestCase初始化的時候會自動調用
* 一般用于初始化公用資源
*/
protected void setUp() {
try {
/**
* 可以采用hibernate.properties或者hibernate.cfg.xml
* 配置文件的初始化代碼
*
* 采用hibernate.properties
* Configuration config = new Configuration();
* config.addClass(TUser.class);
*/
//采用hibernate.cfg.xml配置文件,與上面的方法對比,兩個差異
//1.Configuration的初始化方式
//2.xml
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* JUnit中的tearDown方法在TestCase執行完畢的時候會自動調用
* 一般用于釋放資源
*/
protected void tearDown() {
try {
session.close();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 對象持久化測試(Insert方法)
*/
public void testInsert() {
Transaction tran = null;
try {
tran = session.beginTransaction();
TUserMail user = new TUserMail();
user.setName("byf");
List list = new ArrayList();
list.add("baiyf@msn.com");
list.add("bexy@163.com");
user.setEmail(list);
session.save(user);
session.flush();
tran.commit();
Assert.assertEquals(user.getId().intValue()>0 ,true);
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
if(tran != null) {
try {
tran.rollback();
} catch (Exception e1) {
// TODO: handle exception
e1.printStackTrace();
}
}
}
}
/**
* 對象讀取測試(Select方法)
*/
public void testSelect(){
String hql = " from TUserMail where name='byf'";
try {
List userList = session.createQuery(hql).list();
TUserMail user = (TUserMail)userList.get(0);
List mailList = user.getEmail();
Assert.assertEquals((String)mailList.get(0), "baiyf@msn.com");
Assert.assertEquals((String)mailList.get(1), "bexy@163.com");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
}
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class HibernateTest extends TestCase {
Session session = null;
/**
* JUnit中的setUp方法在TestCase初始化的時候會自動調用
* 一般用于初始化公用資源
*/
protected void setUp() {
try {
/**
* 可以采用hibernate.properties或者hibernate.cfg.xml
* 配置文件的初始化代碼
*
* 采用hibernate.properties
* Configuration config = new Configuration();
* config.addClass(TUser.class);
*/
//采用hibernate.cfg.xml配置文件,與上面的方法對比,兩個差異
//1.Configuration的初始化方式
//2.xml
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* JUnit中的tearDown方法在TestCase執行完畢的時候會自動調用
* 一般用于釋放資源
*/
protected void tearDown() {
try {
session.close();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 對象持久化測試(Insert方法)
*/
public void testInsert() {
Transaction tran = null;
try {
tran = session.beginTransaction();
TUserMail user = new TUserMail();
user.setName("byf");
List list = new ArrayList();
list.add("baiyf@msn.com");
list.add("bexy@163.com");
user.setEmail(list);
session.save(user);
session.flush();
tran.commit();
Assert.assertEquals(user.getId().intValue()>0 ,true);
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
if(tran != null) {
try {
tran.rollback();
} catch (Exception e1) {
// TODO: handle exception
e1.printStackTrace();
}
}
}
}
/**
* 對象讀取測試(Select方法)
*/
public void testSelect(){
String hql = " from TUserMail where name='byf'";
try {
List userList = session.createQuery(hql).list();
TUserMail user = (TUserMail)userList.get(0);
List mailList = user.getEmail();
Assert.assertEquals((String)mailList.get(0), "baiyf@msn.com");
Assert.assertEquals((String)mailList.get(1), "bexy@163.com");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
}
運行測試代碼,觀察數據庫中,可以發現email地址信息已經以";"分隔的形式保存。同時,在數據讀取時,我們也無需面對原始的";"分隔字符串,轉而只需要處理List類型數據即可。
posted on 2006-06-29 16:36 baim 閱讀(1967) 評論(2) 編輯 收藏 所屬分類: 開源軟件框架