`

hibernate 自定义类型映射(转载)

阅读更多
最近做一个很小的系统,其中用到了一个复合主键,本人其实是刚刚开始学习hibernate的,对它的很多的东西都不是很了解。突然发现其实用复合主键是多么的不好。呵呵,个人观点。当然是在发现了hibernate有比它更好的东西是时候才这样说这样想的,这个东西当然就是今天我想说的UserType.故名思义,就是用户自己定义的数据类型。这是一个接口,用户可以实现它以定义出自己的数据类型。下面我们以一个在网 上广为流传的题材为例子给大家讲述一下。就是”用户邮件问题“我是这样叫它的。当我们想为一个用户存多个邮件地址的时候就出现了这个问题。怎么样组织我们的数据库??呵呵,我们这儿为了配合我们的主题当然是要选取一种很特别的组织方式:一个String来存储所有的Email然后在每一个Email之间用一个";"符号分开。很有意思的一种方式,以前可能只有在邮件群发的时候才可能看到吧。先来一点点直观的东西:我的这个示例的整体的文件组织形式图。

           下面我们来一步一步的分析 我们的代码:首先当然是要建好我们的数据库的表:这里就叫user

         它有三个字段:id       int             name         String                        email                   String当然我们对email有特别的要求的。

           下面来看看我们的配置文件:hibernate.cfg.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">

<!-- Generated by MyEclipse Hibernate Tools.                       -->
<hibernate-configuration>

        <session-factory>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/Hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">1111</property>
        <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <mapping resource="com/terence/usertype/user.hbm.xml"/>
        </session-factory>
</hibernate-configuration>

第二个配置文件:user.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.terence.usertype.User" table="user">
              <id name="id" column="id">
              <generator class="increment"></generator>
              </id>
              <property name="name" column="name"></property>
              <property name="email" column="email" type="com.terence.usertype.EmailList"></property>
              </class>
              </hibernate-mapping>

前面这两个文件相对来说比较简单吧!

下面来看一下我们的自定义的数据类型所对谈的类:EmailList.java

package com.terence.usertype;

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.apache.commons.lang.StringUtils;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public class EmailList implements UserType {
//private List emails;      //为什么在网上的程序中都加入了这个属性,但好象没有什么用。
private static final char SPLITTER=';';
private static final int[] TYPES=new int[]{Types.VARCHAR};
//用于设定我们的类是不是可变的。
public boolean isMutable()
{
      return false;
}
//该自定义对象类型所对应的SQL数据的类型。
public int[] sqlTypes()
{
      return TYPES;
}
//用于设定nullSafeGet所返回的数据的类型。即我们的自定义的数据类型。
public Class returnedClass()
{
      return List.class;
}
//该方法用于提供自定义类型的完全的复制的方法。它主要用于构造返回对象。
//当nullSafeGet获取对象后,将会调用这个方法。进行复制一个完全相同的拷贝。
//然后把这个拷贝返回给用户。
public Object deepCopy(Object value) throws HibernateException
{
      List sourcelist=(List)value;
      List targetlist=new ArrayList();
      targetlist.addAll(sourcelist);
      return targetlist;
}
//这是自定义的数据的对比方法。如果返回的是false则hibernate认为数据发生了变化
//将会把变化更新到库的表之中。
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!=strY)return false;
       }
       return true;
      }
      return false;
}
private String assemble(List emaillist)
{
      StringBuffer sb=new StringBuffer();
      for(int i=0;i<emaillist.size()-1;i++)
      {
       sb.append(emaillist.get(i)).append(SPLITTER);
      }
      sb.append(emaillist.get(emaillist.size()-1));
      return sb.toString();
}
private List parse(String email)
{
      String[] strs=StringUtils.split(email,String.valueOf(SPLITTER));
      List emailList=new ArrayList();
      for(int i=0;i<strs.length;i++)
      {
       emailList.add(strs[i]);
      }
      return emailList;
}
//这个方法将在数据保存时使用。本方法可以使用PreparedStatement将数据写入对应的数据库字段中。
//其中的value表示的是要写入的值。index表示的是在statement的参数中的index.
public void nullSafeSet(PreparedStatement ps,Object value,int index)
          throws HibernateException,SQLException
{
      System.out.println("In the set function");
      if(value!=null)
      {
       String str=assemble((List)value);
       Hibernate.STRING.nullSafeSet(ps, str,index);
      }else
      {
       Hibernate.STRING.nullSafeSet(ps, value,index);
      }
}
//从JDBC的ResultSet中获取到数据,然后返回为相应的类型。
//其中names包含了要映射的字段的名称。
public Object nullSafeGet(ResultSet rs,String[] names,Object owner)
           throws HibernateException,SQLException
{
      System.out.println("In the get function");
      String value=(String)Hibernate.STRING.nullSafeGet(rs, names[0]);
      if(value!=null)
      {
       return parse(value);
      }
      else
      {
       return null;
      }
}
//下面的方法一般好象没有什么用。可能是还没有用到吧。
public Object assemble(Serializable arg0, Object arg1)
          throws HibernateException
{     
            return null;  
        }  
  
        public Serializable disassemble(Object arg0) throws HibernateException
        {
            return null;  
        }  
  
        public int hashCode(Object arg0) throws HibernateException
        {
            return 0;  
        }  
  
        public Object replace(Object arg0, Object arg1, Object arg2)
              throws HibernateException
        { 
            return null;  
        }  

}

说明:这个类实现了UserType我们可以使用Eclipse来帮我们生成一部分的代码。其中对每一个有用的方法的用途都进行了比较详细的说明。大家可以仔细一点点的看。

       下面我们来看一下我们的VO的代码:User.java

          package com.terence.usertype;

import java.util.List;

public class User {
private Integer id;
private String name;
private List email;
public User() {
      super();
}
public List getEmail() {
      return email;
}
public void setEmail(List email) {
      this.email = 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;
}
}

最后一步就是来看一下我们的测试的代码:本来想用Junit进行测试的,但为了明白我还是决定用这个让大家都能看明白。Test.java

package com.terence.usertype;
import java.util.List;  
import java.util.ListIterator;  
import org.hibernate.Query;  
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  
  
public class Test {

         public static void main(String[] args) throws Exception{          
             Configuration config = new Configuration().configure();  
             SessionFactory factory = config.buildSessionFactory();  
             Session session = factory.openSession();  
             Query query = session.createQuery("from User as a");  
        
             ListIterator iterator = query.list().listIterator();  
             User tt = (User) iterator.next();
             List emails = tt.getEmail();              
             for (int i = 0; i < emails.size(); i++) {  
                 String emailStr = (String)emails.get(i);  
                 System.out.println(emailStr);  
             }         
             session.close();  
         }       

}

下面是我的测试的结果:

  


log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.

     如果看不明白的可以发邮件给我,我们一起探讨。terence zhao

转载:http://hi.baidu.com/lovelink/item/2e201b28b5c8cec3ee10f1a3
分享到:
评论

相关推荐

    JAVA数据类型与Hibernate的类型映射

    此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...

    Hibernate使用——自定义数据类型

    例如,使用Lombok库可以简化getter和setter的编写,而使用Hibernate Tools可以自动生成实体类和映射文件,这在处理大量自定义类型时非常有用。 总的来说,自定义数据类型是Hibernate的一个强大特性,它使我们能够...

    Hibernate数据类型映射及ID

    标题:“Hibernate数据类型映射及ID” 描述:“Hibernate与各数据库数据类型的映射” ### Hibernate数据类型映射 Hibernate作为一款流行的Java持久层框架,它提供了丰富的数据类型映射功能,使得开发者能够更加...

    Hibernate数据类型映射关系

    关于Hibernate的基本数据类型与Java中基本数据类型的映射关系

    Hibernate数据类型映射表.bmp

    Hibernate数据类型映射表,介绍hibernate中各类型数据的关系!

    hibernate映射Oracle中LONG类型

    "hibernate映射Oracle中LONG类型" Hibernate 框架映射 Oracle 中的 LONG 类型字段是一种复杂的技术问题。Oracle 中的 LONG 类型字段是一种特殊的数据类型,用于存储可变长字符串,最大长度限制是 2GB。这与 Java ...

    简要分析Java的Hibernate框架中的自定义类型

    在Java的Hibernate框架中,自定义类型是一种非常实用的功能,它允许开发者根据特定业务需求扩展Hibernate内置的数据类型。当我们发现Hibernate默认的数据类型无法满足我们存储数据的特殊要求时,例如需要处理复杂...

    hibernate自定义查询

    Hibernate是一款强大的对象关系映射(ORM)框架,它允许开发者使用Java对象来操作数据库,而无需直接编写SQL语句。在Hibernate中,自定义查询是扩展其功能的重要方式,能够帮助我们实现更复杂的数据库交互需求。本文...

    hibernate映射枚举类型

    Hibernate,作为Java中广泛使用的对象关系映射(ORM)框架,提供了一种优雅的方式来映射枚举类型到数据库。本文将深入探讨Hibernate如何映射枚举类型,并给出实际应用示例。 ### Hibernate枚举映射方式 #### 1. `@...

    hibernate array 数组映射

    在Java的持久化框架Hibernate中,数组映射是一种常见的数据模型转换方式,它允许我们将数据库中的数据以数组的形式存储在Java对象中。本篇将详细探讨`hibernate array 数组映射`的相关知识点,包括其原理、配置、...

    hibernate map 集合映射

    Hibernate集合映射类型 - **List**: 映射为数据库中的列表,元素顺序可以被持久化。 - **Set**: 映射为无序且无重复元素的集合,如HashSet。 - **Bag**: 与List类似,但不保证元素顺序,不推荐使用。 - **Map**: ...

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

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

    hibernate集合的映射

    本文将深入探讨Hibernate中的四种主要集合映射类型:Set、List、Array和Map,以及它们在实际开发中的应用场景和配置。 一、Set集合映射 Set集合映射是最常见的映射类型,它不允许重复元素。在Hibernate中,Set通常...

    hibernate关联映射详解

    hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...

    hibernate + 自定义标签分页

    本例中,我们探讨的是如何结合Struts、Hibernate和自定义标签实现分页功能,这是一种常见的优化用户界面体验的技术,特别是对于数据量大的查询结果。 1. **分页原理** 分页的基本思想是将大量数据分成多个小部分,...

    Hibernate对象关系映射

    Hibernate对象关系映射一对多 很基础等文档

    Hibernate 映射类型与Java 类型对照

    理解Hibernate映射类型与Java类型的对应关系对于有效地使用Hibernate至关重要。 首先,我们来看一下基本数据类型的映射。`integer`对应Java中的`int`或`Integer`,在SQL中映射为`INTEGER`类型;`long`对应`long`或`...

    hibernate七种映射

    便于同学们更好的学习hibernate,其中包含了hibernate的七种映射管、关系

    hibernate set 集合映射

    Set是最常见的集合映射类型,它不允许重复元素,与数据库中的唯一约束相对应。 2. **元素类型**:集合中的每个元素都是一个实体对象,它们通常通过@ManyToOne或@OneToOne关联映射到单独的数据库表。 3. **关联映射...

    hibernate复合主键映射

    复合主键映射 &lt;br&gt;通常将复合主键相关属性,单独抽取出来,建立一个独立的类 * 必须实现序列化接口 * 必须实现equals和hashcode方法 采用标签进行映射,其它属性采用正常映射

Global site tag (gtag.js) - Google Analytics