數據庫中存在一個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類型數據即可。