数据库中存在一个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-07-05 14:46
knowhow 阅读(293)
评论(0) 编辑 收藏 所属分类:
ORM:Hibernate及其他