Hibernate自定义数据类型UserType
2011-11-11 12:03
537 查看
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"/>
首先我么创建一个自定义类型的类,让他实现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"/>
相关文章推荐
- hibernate中自定义数据类型的使用---UserType,CompositeUserType接口的使用
- Hibernate UserType 自定义类型
- Hibernate对自定义类型CompositeUserType的用法
- Hibernate中的自定义类型——UserType、CompositeUserType
- Hibernate对自定义类型UserType的用法
- Hibernate使用自定义类型UserType映射Oracle的Date类型
- Hibernate对自定义类型CompositeUserType的用法
- Hibernate对自定义类型UserType的用法
- Hibernate对自定义类型UserType的用法
- Hibernate自定义数据类型映射
- NHibernate实现自定义类型IUserType
- Hibernate实战_笔记33(创建CompositeUserType、参数化定制类型)
- Oracle 自定义数据类型Type
- ABAP开发基础知识:3) 自定义数据类型(User-Defined Data Types)
- SSH框架问题——hbm.xml配置出现的org.hibernate.MappingException: Could not determine type for:(貌似叫数据类型转换错误)问题
- org.hibernate.MappingException: Could not determine type for: String 数据类型错误
- 利用Hibernate自定义UserType简化编程
- 利用sqlite创建一个数据user,其含有一张表person,该person表中含有三个列,其中第一字段为主键int类型的,其他两个字段自定义数据类型和名称。
- QT 信号槽connect中解决自定义数据类型或数组作为函数参数的问题——QT qRegisterMetaType 注册MetaType——关键:注册自定义数据类型或QMap等容器类
- osg源码中的ref_ptr operator unspecified_bool_type() 指向类数据成员的指针&类转化为另一类型(如自定义的C类转化为int)