hibernate之自定义数据类型

简介: 简介     Hibernate的强大用过的童鞋肯定会知道的,通过OR映射我们可以很方便的实现数据库操作,Hibernate对我们一些类型的映射都提供了很好的支持,但是显然也有不给力的地方,比如简单的注册,一个人可能有好多邮箱,对于这个问题怎么做呢?有人说简单,可以另外开一张表,恩,很不错,确

简介


    Hibernate的强大用过的童鞋肯定会知道的,通过OR映射我们可以很方便的实现数据库操作,Hibernate对我们一些类型的映射都提供了很好的支持,但是显然也有不给力的地方,比如简单的注册,一个人可能有好多邮箱,对于这个问题怎么做呢?有人说简单,可以另外开一张表,恩,很不错,确实可以,可是这样有时候可能小题大作了。也有人说,直接将邮箱拼接成字符串然后在存储,这个想法也很好,但在我们读出来的时候就要再进行一次解析操作,将EMAIL还原,这些都要求我们编程人员自己完成。那么Hibernate有没有提供什么好的支持呢?回答是肯定的,Hibernate给我们提供了一个UserType接口,通过UserType我们可以对一些常见的类型进行封转,转变成具有个性的类型。
Center
Center Center

实现UserType的源码:

package com.zhushuai.hibernate;
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;
public class EmailType implements UserType{
	private static final char Spliter=';';
	/**
	 * 自定义类型的完全复制方法,构造返回对象
	 *    1. 当nullSafeGet方法调用之后,我们获得了自定义数据对象,在向用户返回自定义数据之前
	 * deepCopy方法被调用,它将根据自定义数据对象构造一个完全拷贝,把拷贝返还给客户使用。
	 *    2.此时我们就得到了自定义数据对象的两个版本
	 *     原始版本由hibernate维护,用作脏数据检查依据,复制版本由用户使用,hibernate将在
	 * 脏数据检查过程中比较这两个版本的数据。
	 * 
	 * 
	 */
	@Override
	public Object deepCopy(Object value) throws HibernateException {
		List source=(List)value;
		List target=new ArrayList();
		target.addAll(source);
		return target;
	}

	/**
	 * 自定义数据类型比对方法
	 * 用作脏数据检查,X,Y为两个副本
	 */
	@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 ylList=(List)y;
			if (xList.size()!=ylList.size()) {
				return false;
			}
			for(int i=0;i<xList.size();i++){
				String s1=(String)xList.get(i);
				String s2=(String)ylList.get(i);
				if (!s1.equals(s2)) {
					return false;
				}
			}
			return true;
		}
		return false;
	}
	/**
	 * 返回给定类型的hashCode
	 */
	@Override
	public int hashCode(Object value) throws HibernateException {
		return value.hashCode();
	}
	/**
	 * 表示本类型实例是否可变
	 */
	@Override
	public boolean isMutable() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * 读取数据转换为自定义类型返回
	 * names包含了自定义类型的映射字段名称
	 */
	@SuppressWarnings("deprecation")
	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
	throws HibernateException, SQLException {
		//取得字段名称并查询
		 String mail_str=(String)Hibernate.STRING.nullSafeGet(rs,names[0]);  
	        List temp=new ArrayList<String>();  
	        if(mail_str==null)  
	        {  
	            return null;  
	        }  
	        else  
	        {  
	            String[] strs=mail_str.split(";");  
	            for(int i=0;i<strs.length;i++)  
	            {  
	                temp.add(strs[i]);  
	            }  
	            return temp;  
	        } 
	}
	/**
	 * 数据保存时被调用
	 */
	@Override
	public void nullSafeSet(PreparedStatement ps, Object value, int index)
	throws HibernateException, SQLException {
		if(value!=null){
			String str=combain((List)value);
			//保存数据
			Hibernate.STRING.nullSafeSet(ps, str,index);
		}else {
			//空值就直接保存了
			Hibernate.STRING.nullSafeSet(ps,value.toString(),index);
		}
	}	
	private String combain(List list){
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<list.size()-1;i++){
			sb.append(list.get(i)).append(Spliter);
		}
		sb.append(list.get(list.size()-1));
		return sb.toString();
	}
	/**
	 * 修改类型对应的java类型
	 * 我们这边使用LIST类型
	 */
	@Override
	public Class returnedClass() {
		return List.class;
	}
	/**
	 * 修改类型对应的SQL类型
	 * 使用VARCHAR
	 */
	@Override
	public int[] sqlTypes() {
		return new int[]{Types.VARCHAR};
	}
	@Override
	public Object replace(Object arg0, Object arg1, Object arg2)
	throws HibernateException {
		return null;
	}
	/**
	 * 不知干嘛用的
	 */
	@Override
	public Object assemble(Serializable arg0, Object arg1)
	throws HibernateException {
		return null;
	}
	@Override
	public Serializable disassemble(Object arg0) throws HibernateException {
		return null;
	}
}


Student实体类:

package com.zhushuai.hibernate;
import java.util.HashMap;
import java.util.List;
public class Student {
	String id;
	String name;
	int age;
	String birthday;
	List emails;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public List getEmails() {
		return emails;
	}
	public void setEmails(List emails) {
		this.emails = emails;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}	
}

student.hbm.xml的配置:

<?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" >
<hibernate-mapping>
<class name="com.zhushuai.hibernate.Student">
<id name="id"> 
<generator class="uuid"></generator>
</id>
<property name="name" ></property>
<property name="age"></property>
<property name="birthday"></property>
<property name="emails" column="emails" type="com.zhushuai.hibernate.EmailType"/>

</class>
</hibernate-mapping>

client类:

package com.zhushuai.hibernate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Client {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//读取hibernate.cfg.xml文件  
		Configuration cfg = new Configuration().configure();		
		//建立sessionfactory
		SessionFactory sessionfactory = cfg.buildSessionFactory();		
		Session  session = null;
		try{ 
		//开启session
		session = sessionfactory.openSession();		
		//开启事务
		session.beginTransaction();		
		// 插入数据
		/*
		Student student = new Student();
		 List list=new ArrayList<String>(); 
		 list.add("shuai.zhu@kodak.com");
		 list.add("454942607@qq.com");
		student.setAge(23);
		student.setBirthday("1990");
		student.setName("zhushuai");
		student.setEmails(list);
		session.save(student);*/				
		//获取数据
		String hql = "from Student where name='zhushuai'";
		Query query = session.createQuery(hql);		
		List list = query.list();
		Iterator it = list.iterator();
		while(it.hasNext()){
			Student student = (Student) it.next();
			List emailList = student.getEmails();
			for(int i=0;i<emailList.size();i++){
				System.out.println("email  "+i+":"+emailList.get(i));							}			
		}		
		session.getTransaction().commit();
		}catch(Exception e){
			e.getStackTrace();
			 session.getTransaction().rollback();
		}finally{
			if(session != null){  
                if(session.isOpen()){  
                    //关闭session  
                    session.close();  
                }  
            } 
		}		
		// TODO Auto-generated method stub
	}
}

输出结果:
Center



相关文章
|
5月前
|
XML Java 数据库连接
Mybatis引用静态常量或者枚举类型
Mybatis引用静态常量或者枚举类型
128 0
|
11天前
|
存储 XML Java
mybatis使用内部类处理一对多类型数据2
mybatis使用内部类处理一对多类型数据2
|
9月前
MyBatis-Plus之枚举
MyBatis-Plus之枚举
57 0
|
9月前
|
数据库
通用mapper(tk.mybatis) 使用Enum枚举类型字段的注意事项
通用mapper(tk.mybatis) 使用Enum枚举类型字段的注意事项
141 0
|
10月前
|
Java 数据库连接 数据库
MyBatis中解决实体类属性和数据库表的列名不一致的操作
MyBatis中解决实体类属性和数据库表的列名不一致的操作
|
SQL Java 数据库连接
Mybatis 类型处理与别名
数据库类型和 Java 类型之间的映射、在 Mybatis 中使用 TypeHandler 做这个转换
112 0
|
XML SQL Java
Hibernate-ORM:14.Hibernate中的命名查询
      ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------         本篇博客讲述命名查询,所谓命名查询是什么呢? Hibernate中允许我们在xml,实体类,甚至注解的方式来编写查询语句,本篇博客将讲述xml中的方式 一,准备好准备工作,我由于上篇博客把大量的准备都做好,所以,本篇从简 二,预览hbm.
1029 0
|
Java 数据库连接 数据库