最近做一个很小的系统,其中用到了一个复合主键,本人其实是刚刚开始学习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
分享到:
相关推荐
此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...
例如,使用Lombok库可以简化getter和setter的编写,而使用Hibernate Tools可以自动生成实体类和映射文件,这在处理大量自定义类型时非常有用。 总的来说,自定义数据类型是Hibernate的一个强大特性,它使我们能够...
标题:“Hibernate数据类型映射及ID” 描述:“Hibernate与各数据库数据类型的映射” ### Hibernate数据类型映射 Hibernate作为一款流行的Java持久层框架,它提供了丰富的数据类型映射功能,使得开发者能够更加...
关于Hibernate的基本数据类型与Java中基本数据类型的映射关系
Hibernate数据类型映射表,介绍hibernate中各类型数据的关系!
"hibernate映射Oracle中LONG类型" Hibernate 框架映射 Oracle 中的 LONG 类型字段是一种复杂的技术问题。Oracle 中的 LONG 类型字段是一种特殊的数据类型,用于存储可变长字符串,最大长度限制是 2GB。这与 Java ...
在Java的Hibernate框架中,自定义类型是一种非常实用的功能,它允许开发者根据特定业务需求扩展Hibernate内置的数据类型。当我们发现Hibernate默认的数据类型无法满足我们存储数据的特殊要求时,例如需要处理复杂...
Hibernate是一款强大的对象关系映射(ORM)框架,它允许开发者使用Java对象来操作数据库,而无需直接编写SQL语句。在Hibernate中,自定义查询是扩展其功能的重要方式,能够帮助我们实现更复杂的数据库交互需求。本文...
Hibernate,作为Java中广泛使用的对象关系映射(ORM)框架,提供了一种优雅的方式来映射枚举类型到数据库。本文将深入探讨Hibernate如何映射枚举类型,并给出实际应用示例。 ### Hibernate枚举映射方式 #### 1. `@...
在Java的持久化框架Hibernate中,数组映射是一种常见的数据模型转换方式,它允许我们将数据库中的数据以数组的形式存储在Java对象中。本篇将详细探讨`hibernate array 数组映射`的相关知识点,包括其原理、配置、...
Hibernate集合映射类型 - **List**: 映射为数据库中的列表,元素顺序可以被持久化。 - **Set**: 映射为无序且无重复元素的集合,如HashSet。 - **Bag**: 与List类似,但不保证元素顺序,不推荐使用。 - **Map**: ...
本文将深入探讨如何使用Hibernate实现领域对象的自定义字段,这涉及到对Hibernate核心概念的理解以及自定义类型的应用。 首先,我们需要了解Hibernate的核心概念。Hibernate主要通过配置文件(hibernate.cfg.xml)...
本文将深入探讨Hibernate中的四种主要集合映射类型:Set、List、Array和Map,以及它们在实际开发中的应用场景和配置。 一、Set集合映射 Set集合映射是最常见的映射类型,它不允许重复元素。在Hibernate中,Set通常...
hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...
本例中,我们探讨的是如何结合Struts、Hibernate和自定义标签实现分页功能,这是一种常见的优化用户界面体验的技术,特别是对于数据量大的查询结果。 1. **分页原理** 分页的基本思想是将大量数据分成多个小部分,...
Hibernate对象关系映射一对多 很基础等文档
理解Hibernate映射类型与Java类型的对应关系对于有效地使用Hibernate至关重要。 首先,我们来看一下基本数据类型的映射。`integer`对应Java中的`int`或`Integer`,在SQL中映射为`INTEGER`类型;`long`对应`long`或`...
便于同学们更好的学习hibernate,其中包含了hibernate的七种映射管、关系
Set是最常见的集合映射类型,它不允许重复元素,与数据库中的唯一约束相对应。 2. **元素类型**:集合中的每个元素都是一个实体对象,它们通常通过@ManyToOne或@OneToOne关联映射到单独的数据库表。 3. **关联映射...
Hibernate 支持多种集合类型,如 List、Set、Map 等,它们可以作为一对多或多对多关系的容器。`@ElementCollection` 用于映射非实体类属性的集合,而 `@OrderColumn` 可以指定集合元素的排序方式。 6. **级联操作 ...