HIbernate自定义类型 UserType的简单使用

  经典的例子是一个用户对多个邮件的例子,在数据库中,用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);
			    }	
		    }
		    
		}
	}
	
}


你可能感兴趣的:(java,sql,Hibernate,MyEclipse,qq)