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)
);


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;
    }

}


3.
配置文件TUserMail.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 
        Auto-generated mapping file from
        the hibernate.org cfg2hbm engine
-->
    <class name
="cn.blogjava.usertype.TUserMail" table="t_user_mail" catalog="sample">
        <id name
="id" type="integer">
            <column name
="id" />
            <generator class
="native" />
        </id>
        <property name
="name" type="string">
            <column name
="name" length="50" />
        </property>
        <property name
="age" type="integer">
            <column name
="age" />
        </property>
        <property name
="email" type="cn.blogjava.usertype.EMailList">
            <column name
="email" length="300" />
        </property>
    </class>
</hibernate-mapping>

4.
在hibernate.cfg.xml载入TUserMail.hbm.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">com.mysql.jdbc.Driver</property>
        <property name
="hibernate.connection.password">1234</property>
        <property name
="hibernate.connection.url">jdbc:mysql://localhost:3306/sample</property>
        <property name
="hibernate.connection.username">root</property>
        <property name
="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <mapping resource
="cn/blogjava/start/TUser.hbm.xml" />
        <mapping resource
="cn/blogjava/usertype/TUserMail.hbm.xml" />
    </session-factory>
</hibernate-configuration>

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());
        }
    }
}

运行测试代码,观察数据库中,可以发现email地址信息已经以";"分隔的形式保存。同时,在数据读取时,我们也无需面对原始的";"分隔字符串,转而只需要处理List类型数据即可。

posted on 2006-06-29 16:36 baim 阅读(1961) 评论(2)  编辑  收藏 所属分类: 开源软件框架

评论

# re: Hibernate映射自定义数据类型 2006-08-14 15:16 kocr

其实作者应该在文中给出数据库的响应表结构和关联关系,这样给人一目了然和清晰的感觉。个人愚见。  回复  更多评论   

# re: Hibernate映射自定义数据类型[未登录] 2007-08-27 18:56 哈哈

Could not determine type for: entity.EMailList, for columns: [org.hibernate.mapping.Column(email)

为什么老是报这个错误  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2006年8月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

常用链接

随笔分类(27)

随笔档案(28)

搜索

最新评论