您的位置:首页 > 其它

Hibernate映射自定义数据类型

2013-07-31 15:57 363 查看
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类型数据即可。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: