`

Hibernate映射自定义数据类型

 
阅读更多

数据库中存在一个email字段,并允许其中存储多个email地址,各地址之间使用 ; 分割,但是在POJO中,为了便于处理,email定义为一个List对象。
如何将String字段映射为List类型,Hibernate并没有提供原生支持,需要我们实现自己的UserType。
1.数据库定义

DROP   TABLE  t_user;

CREATE   TABLE  t_user (
       id  INT   NOT   NULL  AUTO_INCREMENT
     , name  VARCHAR ( 50 )
     , age  INT
     , email  VARCHAR ( 300 )
     ,  PRIMARY   KEY  (id)
); 

 

2.实现了UserType的自定义数据类型类EmailList

package tuser;

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 EmailList implements UserType {
	private static final char SPLITTER = ';';
	private static final int[] TYPES = new int[]{Types.VARCHAR};
	
	@Override
	public int[] sqlTypes() {
		return TYPES;
	}

	@Override
	public Class returnedClass() {
		return List.class;
	}

	@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 index = 0; index < xList.size(); index++){
				String str1 = (String) xList.get(index);
				String str2 = (String) yList.get(index);
				if(str1 != str2){
					return false;
				}
			}
			
			return true;
		}
		
		return false;
	}

	@Override
	public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
			throws HibernateException, SQLException {
		String value = Hibernate.STRING.nullSafeGet(rs, names[0]);
		if(value != null){
			return parse(value);
		}else{
			return null;
		}
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index)
			throws HibernateException, SQLException {
		System.out.println("Set method executed");
		if(value != null){
			String str = assemble((List)value);
			Hibernate.STRING.nullSafeSet(st, str, index);
		}else{
			Hibernate.STRING.nullSafeSet(st, null, index);
		}
	}

	@Override
	public Object deepCopy(Object value) throws HibernateException {
		List sourceList = (List)value;
		List targetList = new ArrayList();
		targetList.addAll(sourceList);
		
		return targetList;
	}

	@Override
	public boolean isMutable() {
		return false;
	}

	/**
	 * 将String拼装为一个字符串,以“;”分隔
	 * @param emailList
	 * @return
	 */
	private String assemble(List emailList){
		StringBuffer strBuf = new StringBuffer();
		for(int i = 0; i < emailList.size() - 1; i++){
			strBuf.append(emailList.get(i)).append(SPLITTER);
		}
		strBuf.append(emailList.get(emailList.size() - 1));
		
		return strBuf.toString();
	}
	
	/**
	 * 将以“;”分隔的字符串解析为一个字符串数组
	 * @param value
	 * @return
	 */
	private List parse(String value){
		String[] strs = value.split(SPLITTER + "");
		List emailList = new ArrayList();
		for(int i = 0; i < strs.length; i++){
			emailList.add(strs[i]);
		}
		
		return emailList;
	}

	@Override
	public Object assemble(Serializable arg0, Object arg1)
			throws HibernateException {
		return null;
	}

	@Override
	public Serializable disassemble(Object arg0) throws HibernateException {
		return null;
	}

	@Override
	public int hashCode(Object arg0) throws HibernateException {
		return 0;
	}

	@Override
	public Object replace(Object arg0, Object arg1, Object arg2)
			throws HibernateException {
		return null;
	}
}

 

3.配置文件TUser.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="tuser.TUser" table="T_USER">
		<id name="id" type="java.lang.Integer">
			<column name="ID"/>
			<generator class="native"></generator>
		</id>
		<property name="name" type="java.lang.String">
			<column name="NAME"/>
		</property>
		<property name="age" type="java.lang.String">
			<column name="AGE"/>
		</property>
		<property name="email" type="tuser.EmailList">
			<column name="EMAIL"/>
		</property>

	</class>
</hibernate-mapping>

 

4.在hibernate.cfg.xml载入TUser.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
		<property name="connection.driver_class">
			com.mysql.jdbc.Driver
		</property>
		<property name="connection.url">
			jdbc:mysql://localhost:3306/hibernate
		</property>
		<property name="connection.username">
			root
		</property>
		<property name="connection.password">
			system
		</property>
		<property name="dialect">
			org.hibernate.dialect.MySQLDialect
		</property>
		<property name="javax.persistence.validation.mode">
			none
		</property>
		
		
		<property name="c3p0.min_size">5</property>
		<property name="c3p0.max_size">20</property>
		<property name="c3p0.timeout">300</property>
		<property name="c3p0.max_statements">50</property>
		<property name="c3p0.idle_test_period">3000</property>
		
		
		<property name="show_sql">false</property>
		<property name="format_sql">false</property>
		
		<mapping resource="hello/Message.hbm.xml"/>
		<mapping resource="user/User.hbm.xml"/>
		<mapping resource="tuser/TUser.hbm.xml"/>

	</session-factory>
</hibernate-configuration>

 

5.测试类HibernateTest.java

package test;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import tuser.TUser;
import user.User;

public class HibernateTest extends TestCase {
	Session session = null;
	
	@Before
	protected void setUp() throws Exception {
		try {
			Configuration configure = new Configuration().configure();
			SessionFactory sessionFactory = configure.buildSessionFactory();
			session = sessionFactory.openSession();
		} catch (HibernateException e) {
			e.printStackTrace();
		}
	}

	@After
	protected void tearDown() throws Exception {
		try {
			session.close();
		} catch (HibernateException e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testTUser(){
		Transaction tran = null;
        try {
            tran = session.beginTransaction();
            TUser user = new TUser();
            user.setName("byf");
            List list = new ArrayList();
            list.add("baiyf@msn.com");
            list.add("bexy@163.com");
            user.setEmail(list);
            session.save(user);
            session.flush();
            tran.commit();
            Assert.assertEquals(user.getId().intValue()>0 ,true);
        } catch (HibernateException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
            if(tran != null) {
                try {
                    tran.rollback();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
	}
	
	/**
     * 对象读取测试(Select方法)
     */            
    public void testSelect(){
        String hql = " from TUser where name='byf'";
        try {
            List userList = session.createQuery(hql).list();
            TUser user = (TUser)userList.get(0);
            List mailList = user.getEmail();

            Assert.assertEquals((String)mailList.get(0), "baiyf@msn.com");
            Assert.assertEquals((String)mailList.get(1), "bexy@163.com");
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }
}

 

6.TUser类

package tuser;

import java.io.Serializable;
import java.util.List;

public class TUser implements Serializable {
	private static final long serialVersionUID = 1901560971512450430L;

	private Integer id;
	private String name;
	private Integer age;
	private List email;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public List getEmail() {
		return email;
	}
	public void setEmail(List email) {
		this.email = email;
	}
}

 

运行测试代码,观察数据库中,可以发现email地址信息已经以";"分隔的形式保存。同时,在数据读取时,我们也无需面对原始的";"分隔字符串,转而只需要处理List类型数据即可。

分享到:
评论

相关推荐

    运用Hibernate来支持在Oracle中的Java3D虚拟场景

    在Oracle中,一个基于...3D模型在Oracle 11g空间数据中存储和建模,也开发了2个自定义Java类来映射Oracle 11g空间类型中的SDO_GEOMETRY数据类型,用于解决Hibernate目前不支持对SDO_GEOMETRY数据类型进行映射的问题。

    张开涛 hibernate杂谈

    1.4 Hibernate自定义类型 对象---&gt;序列化为字符串 存储 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 1.5 Hibernate自定义类型 集合---&gt;字符串 存储 . . . . . . . . . . . . . . ....

    hibernate杂谈

    1.4 Hibernate自定义类型 对象---&gt;序列化为字符串 存储 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48 1.5 Hibernate自定义类型 集合---&gt;字符串 存储 . . . . . . . . . . . . ...

    Hibernate+中文文档

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...

    hibernate3.2中文文档(chm格式)

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...

    HibernateAPI中文版.chm

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...

    Hibernate中文详细学习文档

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...

    hibernate 教程

    Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 持久化枚举(Persistent enum)类型 5.2.4. 自定义值类型 5.2.5. 映射到"任意"(any)类型 5.3. SQL中引号包围...

    Hibernate 中文 html 帮助文档

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...

    最全Hibernate 参考文档

    5.2.3. 自定义值类型 5.3. SQL中引号包围的标识符 5.4. 其他元数据(Metadata) 5.4.1. 使用 XDoclet 标记 5.4.2. 使用 JDK 5.0 的注解(Annotation) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    hibernate 体系结构与配置 参考文档(html)

    自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated ...

    Hibernate教程

    6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...

    Hibernate使用技巧汇总

    Collection类型属性中 &lt;br&gt;............... &lt;br&gt; ............... &lt;br&gt; 27.Spring的参数化事务管理功能相当强大,笔者建议在基于Spring Framework的应用 开发中,尽量使用容器管理事务,以获得...

    hibernate

    Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 持久化枚举(Persistent enum)类型 5.2.4. 自定义值类型 5.2.5. 映射到"任意"(any)类型 5.3. SQL中引号包围...

    hibernate3.04中文文档.chm

    6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...

    Hibernate3+中文参考文档

    5.2.3. 自定义值类型 5.3. SQL中引号包围的标识符 5.4. 其他元数据(Metadata) 5.4.1. 使用 XDoclet 标记 5.4.2. 使用 JDK 5.0 的注解(Annotation) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent ...

    hibernate 框架详解

    自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...

    Hibernate3的帮助文档

    6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. 使用 JDK 5.0 的注解(Annotation) 7. 集合类(Collections)映射 7.1. 持久化集合类(Persistent ...

    Hibernate参考文档

    5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet 标记 5.5.2. 使用 JDK 5.0 的注解(Annotation) 5.6. 数据库生成属性(Generated Properties...

Global site tag (gtag.js) - Google Analytics