经典的例子是一个用户对多个邮件的例子,在数据库中,用varchar存储,逗号或者分号隔开,而在程序中用数组或者List来操作。直接贴代码:
java vo:
package org.vo;
import java.util.List;
public class Tuser implements java.io.Serializable {
// Fields
private Integer toid;
private String name;
private Integer age;
private List email;
// Constructors
public List getEmail() {
return email;
}
public void setEmail(List email) {
this.email = email;
}
/** default constructor */
public Tuser() {
}
/** full constructor */
public Tuser(String name, Integer age) {
this.name = name;
this.age = age;
}
// Property accessors
public Integer getToid() {
return this.toid;
}
public void setToid(Integer toid) {
this.toid = toid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
}
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<!-- entity-name="DynamicUserMap" 假如把name属性换成这个,那么可以映射成map 但一般不提倡这样用 -->
<class name="org.vo.Tuser" table="tuser" >
<id name="toid" type="java.lang.Integer">
<column name="toid" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="10">
<comment>姓名</comment>
</column>
</property>
<property name="age" type="java.lang.Integer">
<column name="age">
<comment>年龄</comment>
</column>
</property>
<!--注意:此时的type是下面自定义的类型-->
<property name="email" type="org.vo.EmailList">
<column name="email">
<comment>邮箱</comment>
</column>
</property>
</class>
</hibernate-mapping>
下面是自定义的类型,实现UserType接口
package org.vo;
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.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
/**
* 自定义数据类型
*
* @author afei
*
*/
public class EmailList implements UserType {
private List emails;
private static final String SPLITTER = ";";
private static final int[] TYPES = new int[] { Types.VARCHAR };
/**
* 深度copy一个副本给用户使用,脏数据检查时候发现不相同,会执行相应的持久化操作 在这里创建一个新的list,包含原来的所有元素
*/
@Override
public Object deepCopy(Object value) throws HibernateException {
List sourcelist = (List) value;
List targetlist = new ArrayList();
if(sourcelist!=null){
targetlist.addAll(sourcelist);
}
return targetlist;
}
@Override
public Serializable disassemble(Object arg0) throws HibernateException {
System.out.println("disassemble()");
return null;
}
/**
* 此方法用户账数据检查,假如返回false,则认为数据发生变化,并将变化更新到库表中 这里判断email list是否发生改变
*/
@Override
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 strx = (String) xList.get(i);
String stry = (String) yList.get(i);
if (!(strx.equals(stry)))
return false;
}
return true;
}
return false;
}
@Override
public int hashCode(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return 0;
}
/**
* 本类型实例是否可变
*/
@Override
public boolean isMutable() {
return false;
}
/**
* 从JDBC ResultSet读取数据,将其转换为自定义类型后返回 (此方法要求对可能出现的null值进行处理)
* names中包含了当前自定义类型的映射字段名称
*/
@Override
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;
}
}
/**
* 自定义方法,将";"分隔的字符串解析为一个字符串数组
* @return
*/
private List parse(String value){
String[] args=value.split(SPLITTER);
List<String> emailList=new ArrayList<String>();
for(String email:args){
emailList.add(email);
}
return emailList;
}
/**
* 本方法将在hibernate进行数据保存时调用 我们可以通过PreparedStatement将自定义数据写入对应的库表字段
* 将List型的email用";"分隔后存入数据库
*/
@Override
public void nullSafeSet(PreparedStatement ps, Object value, int index)
throws HibernateException, SQLException {
if(value!=null){
Object str=this.assemble((List)value);
Hibernate.STRING.nullSafeSet(ps,str,index);
}else{
Hibernate.STRING.nullSafeSet(ps,value,index);
}
}
@Override
public Object assemble(Serializable str, Object emailList)
throws HibernateException {
return null;
}
/**
* 以字符串拼接
*/
public String assemble(List emailList)
throws HibernateException {
String str="";
for(Object email:emailList){
if(str.equals("")){
str=(String)email;
}else{
str=str+SPLITTER+(String)email;
}
}
System.out.println("assemble");
return str;
}
@Override
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
// TODO Auto-generated method stub
return null;
}
/**
* UserType.nullSafeGet()所返回的自定义数据类型
*/
@Override
public Class returnedClass() {
return List.class;
}
/**
* 返回UserType所映射字段的类型(java.sql.Types) 返回类型为int[],其中包含了映射各字段的SQL类型代码
* (UserType可以映射到一个或多个字段)
*/
@Override
public int[] sqlTypes() {
// TODO Auto-generated method stub
return TYPES;
}
}
ok,咱们做实验:
package org;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.EntityMode;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.usertype.UserType;
import org.util.HibernateSessionFactory;
import org.vo.Tuser;
public class TestHib {
/**
* @param args
*/
public static void main(String[] args) {
Tuser user=new Tuser();
user.setName("hehe1");
user.setAge(20);
List<String> emailList=new ArrayList<String>();
emailList.add("[email protected]");
emailList.add("[email protected]");
user.setEmail(emailList);
add(user);
printVos();
}
public static void add(Tuser user){
Session session=HibernateSessionFactory.getSession();
Transaction tran=session.beginTransaction();
session.save(user);
tran.commit();
}
public static void printVos(){
Session session=HibernateSessionFactory.getSession();
List<Tuser> list=session.createQuery(" from Tuser ").list();
for(Tuser u:list){
List<String> emailList=u.getEmail();
System.out.println(u.getName()+" "+u.getAge()+" "+emailList);
if(emailList!=null){
for(String e:emailList){
System.out.println(e);
}
}
}
}
}