`
sudalyl
  • 浏览: 100473 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

Hibernate自定义数据类型---UserType

阅读更多

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

 

    首先我么创建一个自定义类型的类,让他实现UserType接口:

 

/**
 * @author :LYL
 *@date:2011-4-26,下午08:39:42
 */
package com.lyl.hibernate.mytype;

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;

import com.opensymphony.oscache.util.StringUtil;

public class ArrayType 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 value=(String)Hibernate.STRING.nullSafeGet(rs, names[0]);
		if (value!=null) {
			return parse(value);
		}else {
			return null;
		}

	}

	/**
	 * 数据保存时被调用
	 */
	@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);
		}
	}

	/**
	 * 将数据解析为LIST返回
	 * @param value
	 * @return
	 */
	private List parse(String value){
		List list=StringUtil.split(value, Spliter);
		return list;
	}

	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;
	}
}

 

然后我们在配置OR映射文件时,指定一下自己的类型:

<property name="emails" column="emails" type="com.lyl.hibernate.mytype.ArrayType"/>

 

之后我们运行起来,给EMAILS传LIST类型的即可保存,读出来也是LIST类型,是不是很方便?

1
4
分享到:
评论
1 楼 zhang1303483789 2017-05-17  

相关推荐

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     11.2.2 用UserType映射枚举类型  11.2.3 实现CompositeUserType接口  11.2.4 运行本节范例程序  11.3 操纵Blob和Clob类型数据  11.4 小结  11.5 思考题 第12章 映射继承关系  12.1 继承关系树的每个具体类...

    ssh(structs,spring,hibernate)框架中的上传下载

     fileContent字段映射为Spring所提供的BlobByteArrayType类型,BlobByteArrayType是用户自定义的数据类型,它实现了Hibernate 的org.hibernate.usertype.UserType接口。BlobByteArrayType使用从sessionFactory获取...

    Hibernate实战(第2版 中文高清版)

     8.3.1 定制SQL名称和数据类型   8.3.2 确保数据一致性   8.3.3 添加领域约束和列约束   8.3.4 表级约束   8.3.5 数据库约束   8.3.6 创建索引   8.3.7 添加辅助的DDL   8.4 小结  第三部分 会话...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     11.2.2 用UserType映射枚举类型  11.2.3 实现CompositeUserType接口  11.2.4 运行本节范例程序  11.3 操纵Blob和Clob类型数据  11.4 小结  11.5 思考题 第12章 映射继承关系  12.1 继承关系树的每个具体类...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     11.2.2 用UserType映射枚举类型  11.2.3 实现CompositeUserType接口  11.2.4 运行本节范例程序  11.3 操纵Blob和Clob类型数据  11.4 小结  11.5 思考题 第12章 映射继承关系  12.1 继承关系树的每个具体类...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     11.2.2 用UserType映射枚举类型  11.2.3 实现CompositeUserType接口  11.2.4 运行本节范例程序  11.3 操纵Blob和Clob类型数据  11.4 小结  11.5 思考题 第12章 映射继承关系  12.1 继承关系树的每个具体类...

    VC开发工具使用技巧源代码_usertype.zip

    VC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zipVC开发工具使用技巧源代码_usertype.zip

    商业编程-源码-VC开发工具使用技巧源代码 usertype.zip

    商业编程-源码-VC开发工具使用技巧源代码 usertype.zip

    CUDA SDK 语法高亮必备 usertype.dat

    在VS中配置CUDA时,本身是不识别CUDA关键字的,关键字不能高亮。早期的CUDA版本在SDK中提供了usertype.dat,其中包含CUDA的关键字,但后来的CUDA没有这个文件,网上找了好久,现在贴出来亲测可用~

    VS2005编辑器支持着色器语法高亮,一个完整的usertype.dat

    1. 创建或编辑usertype.dat文件(此文件在VS安装目录下的Common7\IDE下面,比如我的就在D:\Program Files\Microsoft Visual Studio 8\Common7\IDE\usertype.dat),添加如下的关键字列表,每个单词占一行,如果你想...

    usertype.dat

    HLSL的关键字,放在vs的IDE文件下,以在vs中高亮HLSL的关键字

    portal-backend:使用NodeJ构建的Job Portal后端

    - UserType - PasswordResetter - Profile&#40;Foreign&#41;[nulluble] - Company(Foreign)[nullable] - Role(Foreign) 订阅内容 - Id - Name - Email - Status 工作 - Id - Organisation - Location - Grade - ...

    spring aop+自定义注解+反射实现统一校验脚手架

    初始化工程,支持基本数据格式校验 mark 2018.5.21 一口气写完的,还没有怎么测试,先提交上来再说 remark:最近刚到新公司接收项目,发现这里校验参数的没有做,纯硬编码的起判参数的值,主要是为了处理前端传的...

    hibernate3.6 文档(pdf 格式)

    1.1. Part 1 - The first Hibernate Application ................................................................ 1 1.1.1. Setup .............................................................................

    hibernate_test

    Hibernate测试存储和检索 SmartMeter 数据。 对于Hibernate部分,我在这里得到了灵感: : jodatime 和 hybernate .... 没那么容易。 需要使用这个:添加到 build.gradle compile 'org.jadira.usertype:usertype.joda...

    wow-rn-live-stream

    React本机哇直播流实时流媒体组件是React Native Jitsi( )之上的自定义包装器安装$ npm install react-native-wow-rn-live-stream --save用法import { LiveStreamComp } from 'react-native-wow-rn-live-stream' ;...

    数据库超市管理系统.doc

    " "Spoilage "损坏商品表 " 自定义数据类型(custem) "字段名 "数据类型 "长度 "主/外键 "字段值约 "对应中文名 " " " " " "束 " " "gcxCaption"Varchar "100 " "Not null "实体名称 " "gxcID "Int "4 "P "Not null ...

    数据库超市管理系统(1).doc

    " "Spoilage "损坏商品表 " 自定义数据类型(custem) "字段名 "数据类型 "长度 "主/外键 "字段值约 "对应中文名 " " " " " "束 " " "gcxCaption"Varchar "100 " "Not null "实体名称 " "gxcID "Int "4 "P "Not null ...

    飞恒进销存管理系统v7.21(源代码)

    V5.1之后的修改(2006-01-20 至 2007-1-27) ----------------------------------------------------------------------------- ...1、修正UserType=102时利润就不对的问题 2008-04-14 V7.18_4: 1、增加一品多码功能...

Global site tag (gtag.js) - Google Analytics