`
AngelAndAngel
  • 浏览: 234354 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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("6646590081@qq.com");
	     emailList.add("2957375892@qq.com");
	     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的Hibernate框架中的自定义类型

    使用自定义类型时,你需要在实体类的属性上使用`@Type`注解,指定自定义类型的实现类,使得Hibernate在操作这些属性时能够调用我们定义的转换逻辑。 例如,如果你有一个自定义日期时间类型,可以这样使用: ```java...

    用Hibernate实现领域对象的自定义字段

    本文将深入探讨如何使用Hibernate实现领域对象的自定义字段,这涉及到对Hibernate核心概念的理解以及自定义类型的应用。 首先,我们需要了解Hibernate的核心概念。Hibernate主要通过配置文件(hibernate.cfg.xml)...

    hibernate映射Oracle中LONG类型

    使用自定义类型映射 Oracle 中的 LONG 类型字段是解决 Hibernate 框架中 LONG 类型字段读写问题的一种有效方法。通过实现 UserType 接口,我们可以定制 LONG 类型字段的读写操作,并提高 Hibernate 框架的灵活性和可...

    mysql 让hibernate支持text字段的方言

    - 如果使用的是HBM(Hibernate Mapping)文件,需要在对应字段上配置`type`属性,指向自定义的`UserType`全限定类名。 通过以上步骤,你可以确保Hibernate在处理MySQL的`TEXT`字段时能够正确地进行序列化、反序列...

    hibernate 杂谈

    4. **Hibernate自定义类型** Hibernate允许开发者自定义数据类型,将复杂对象如集合转化为字符串存储。这通常涉及到实现`UserType`接口,覆盖其中的方法如`sqlTypes()`、`returnedClass()`等。自定义类型可以用于...

    hibernate4.1中文api

    - **使用org.hibernate.usertype.UserType**: 实现自定义用户类型。 - **使用org.hibernate.usertype.CompositeUserType**: 映射复合类型。 - **类型注册**: 注册自定义类型。 #### 7. 集合映射 - **持久化集合*...

    Hibernate3.2EnumTypeMapping-demo.zip

    - `TYPE`:自定义类型映射,需要实现`org.hibernate.usertype.UserType`接口,可以自定义存储和读取的逻辑。 2. **配置枚举类型映射**: 在Hibernate的映射文件(.hbm.xml)中,可以使用`&lt;typedef&gt;`元素定义枚举...

    Hibernate 配置跟数据库字段的对应关系

    最后,要注意的是,Hibernate还支持自定义类型映射,通过实现`org.hibernate.usertype.UserType`接口,可以自定义任何复杂的数据类型转换。 总结来说,配置Hibernate与数据库字段的对应关系主要包括以下几个步骤: ...

    Hibernate的char问题.txt

    为了更精确地控制 `char` 类型的处理方式,可以考虑使用 Hibernate 提供的自定义类型,比如 `CharacterType` 或者自定义实现 `org.hibernate.usertype.UserType` 接口来创建自定义的类型转换器。 ##### 3. 参数绑定...

    J2EE企业级项目开发-1期 04 Hibernate使用经验.doc

    3. **自定义UserType实例**:例如,如果我们需要在`TUSER`表中存储用户的电子邮件,但不想为每个邮箱创建单独的记录,可以使用`UserType`将多个邮箱地址存储在一个`VARCHAR`字段内,以分号分隔。自定义的`Email`类...

    hibernate-json:Json 用户类型Hibernate

    4. **注册UserType**:在Hibernate配置文件中,你需要为使用自定义JSON类型的属性指定这个UserType。这通常通过在实体类的属性上使用`@Type`注解完成。 例如,如果你使用Jackson库,一个简单的UserType实现可能如下...

    hibernate(api 介绍).docx

    1. org.hibernate.usertype.UserType:可以自定义数据映射类型。 2. org.hibernate.dialect.Dialect abstract_class:Hibernate 对于每种数据库都定义了独有的方言,比如 Oracle、MSSQL、Sybase 等数据库系统都有...

    hibernate(api_介绍)

    此外,还可以通过实现UserType和CompositeUserType接口自定义数据映射。 5. **可扩展接口** - **Dialect**:这是Hibernate的方言抽象类,为不同的数据库系统(如Oracle、MSSQL、Sybase)提供了特定的方言实现,以...

    JSP 中Hibernate实现映射枚举类型

    本文将详细介绍如何在Hibernate中实现枚举类型到数据库的映射,包括对应的枚举类的定义、自定义UserType以及在映射文件hbm.xml中的配置。 首先,定义一个枚举类型Gender,它包含了性别相关的几个枚举值,分别是...

    动态添加hibernate domain的属性的例子

    3. **注册UserType**:在Hibernate的配置文件中,或者在SessionFactory创建时,注册这些UserType实现,让Hibernate知道如何处理这些自定义类型。 4. **存储和检索动态属性**:在数据库中,可以使用一个BLOB或CLOB...

    Hibernate学习笔记

    例如,usertype文件可能展示了如何自定义类型,通过实现UserType接口,将自定义的Java类型与数据库类型进行映射。 五、查询机制 1. HQL(Hibernate Query Language):面向对象的查询语言,类似SQL但语法更为简洁,...

    Hibernate4实战 之第七部分

    当需要持久化某些来自第三方库的Java类型时,如果这些类型没有提供适当的getter和setter方法,可以考虑实现`org.hibernate.UserType`接口来定义自定义类型。这样可以在不修改原有类的情况下完成持久化任务。 #### ...

    hibernate_persistence第02-16章书中源码

    在Hibernate中,你可以通过实现UserType接口来自定义数据类型的映射,使非标准的Java类型能够被持久化。"BKBLX"可能是对“备份策略”的简称,表明这部分内容可能涉及到如何自定义类型以适应特定的备份需求。 7. **...

    hibernate3中文手册

    11. **自定义类型**:如果需要对特殊类型的属性进行映射,可以实现UserType接口来自定义类型。 12. **实体状态管理**:区分临时态、持久态、游离态和删除态,理解它们之间的转换过程。 13. **性能优化**:包括...

Global site tag (gtag.js) - Google Analytics