数据库中存在一个email字段,并允许其中存储多个email地址,各地址之间使用 ; 分割,但是在POJO中,为了便于处理,email定义为一个List对象。
如何将String字段映射为List类型,Hibernate并没有提供原生支持,需要我们实现自己的UserType。
1.数据库定义
DROP TABLE t_user_mail;
CREATE TABLE t_user_mail (
id INT NOT NULL AUTO_INCREMENT
, name VARCHAR ( 50 )
, age INT
, email VARCHAR ( 300 )
, PRIMARY KEY (id)
);
2.
实现了UserType的自定义数据类型类EMailList
package cn.blogjava.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 static final char SPLITTER = ' ; ' ;
private static final int [] TYPES = new int [] {Types.VARCHAR};
public int [] sqlTypes() {
// TODO Auto-generated method stub
return TYPES;
}
public Class returnedClass() {
// TODO Auto-generated method stub
return List. class ;
}
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 str1 = (String)xlist.get(i);
String str2 = (String)ylist.get(i);
if ( ! str1.equals(str2)) return false ;
}
return true ;
}
return false ;
}
public int hashCode(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return 0 ;
}
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 ;
}
}
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (value != null ) {
String str = assemble((List)value);
Hibernate.STRING.nullSafeSet(st, str, index);
} else {
Hibernate.STRING.nullSafeSet(st, value, index);
}
}
public Object deepCopy(Object value) throws HibernateException {
List sourceList = (List)value;
List targetList = new ArrayList();
targetList.addAll(sourceList);
return targetList;
}
public boolean isMutable() {
// TODO Auto-generated method stub
return false ;
}
public Serializable disassemble(Object arg0) throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object assemble(Serializable arg0, Object arg1)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
public Object replace(Object arg0, Object arg1, Object arg2)
throws HibernateException {
// TODO Auto-generated method stub
return null ;
}
private String assemble(List emailList) {
StringBuffer strBuf = new StringBuffer();
for ( int i = 0 ; i < emailList.size() - 1 ; i ++ ) {
strBuf.append((String)emailList.get(i)).append(SPLITTER);
}
strBuf.append(emailList.get(emailList.size() - 1 ));
return strBuf.toString();
}
private List parse(String value) {
String[] strs = StringUtils.split(value, SPLITTER);
List emailList = new ArrayList();
for ( int i = 0 ; i < strs.length; i ++ ) {
emailList.add(strs[i]);
}
return emailList;
}
}
3.
配置文件TUserMail.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!--
Auto-generated mapping file from
the hibernate.org cfg2hbm engine
-->
<class name="cn.blogjava.usertype.TUserMail" table="t_user_mail" catalog="sample">
<id name="id" type="integer">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="string">
<column name="name" length="50" />
</property>
<property name="age" type="integer">
<column name="age" />
</property>
<property name="email" type="cn.blogjava.usertype.EMailList">
<column name="email" length="300" />
</property>
</class>
</hibernate-mapping>
4.
在hibernate.cfg.xml载入TUserMail.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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">1234</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sample</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping resource="cn/blogjava/start/TUser.hbm.xml" />
<mapping resource="cn/blogjava/usertype/TUserMail.hbm.xml" />
</session-factory>
</hibernate-configuration>
5.
测试类HibernateTest.java
package cn.blogjava.usertype;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
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;
public class HibernateTest extends TestCase {
Session session = null;
/**
* JUnit中的setUp方法在TestCase初始化的时候会自动调用
* 一般用于初始化公用资源
*/
protected void setUp() {
try {
/**
* 可以采用hibernate.properties或者hibernate.cfg.xml
* 配置文件的初始化代码
*
* 采用hibernate.properties
* Configuration config = new Configuration();
* config.addClass(TUser.class);
*/
//采用hibernate.cfg.xml配置文件,与上面的方法对比,两个差异
//1.Configuration的初始化方式
//2.xml
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* JUnit中的tearDown方法在TestCase执行完毕的时候会自动调用
* 一般用于释放资源
*/
protected void tearDown() {
try {
session.close();
} catch (HibernateException e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 对象持久化测试(Insert方法)
*/
public void testInsert() {
Transaction tran = null;
try {
tran = session.beginTransaction();
TUserMail user = new TUserMail();
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) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
if(tran != null) {
try {
tran.rollback();
} catch (Exception e1) {
// TODO: handle exception
e1.printStackTrace();
}
}
}
}
/**
* 对象读取测试(Select方法)
*/
public void testSelect(){
String hql = " from TUserMail where name='byf'";
try {
List userList = session.createQuery(hql).list();
TUserMail user = (TUserMail)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) {
// TODO: handle exception
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
}
运行测试代码,观察数据库中,可以发现email地址信息已经以";"分隔的形式保存。同时,在数据读取时,我们也无需面对原始的";"分隔字符串,转而只需要处理List类型数据即可。
from:http://www.blogjava.net/knowhow/archive/2006/06/29/55774.html
分享到:
相关推荐
本篇文章将深入探讨如何在Hibernate中实现自定义数据类型。 首先,我们需要理解Hibernate是如何处理数据类型的。默认情况下,Hibernate使用Java的标准数据类型来映射数据库中的列。例如,Integer对应INT,String...
此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...
在Java编程中,枚举类型(Enum)是一种...正确地映射枚举类型可以增强代码的可读性和可维护性,同时减少因数据类型转换导致的潜在错误。在实际开发中,我们应该根据业务场景和枚举特性的需求,选择最合适的映射策略。
在Java的Hibernate框架中,自定义类型是一种非常实用的功能,它允许开发者根据特定业务需求扩展Hibernate内置的数据类型。当我们发现Hibernate默认的数据类型无法满足我们存储数据的特殊要求时,例如需要处理复杂...
"hibernate映射Oracle中LONG类型" Hibernate 框架映射 Oracle 中的 LONG 类型字段是一种复杂的技术问题。Oracle 中的 LONG 类型字段是一种特殊的数据类型,用于存储可变长字符串,最大长度限制是 2GB。这与 Java ...
此外,Hibernate还支持自定义数据类型的映射,允许开发者根据需求扩展和定制。 在实际开发中,理解这些映射关系至关重要,因为它直接影响到数据的存储和查询效率,以及数据的一致性和完整性。例如,如果错误地将...
映射文件包含了类名、表名、字段及其数据类型等信息。例如: ```xml <hibernate-mapping> </hibernate-mapping> ``` 在上述示例中,`User`类与`users`表对应,`id`字段表示主键,`username`和`...
### 常用Hibernate映射配置详解 #### 1. hibernate-mapping节点解析 `hibernate-mapping`节点是Hibernate映射文件中的顶级节点,用于定义一系列配置选项,控制整个映射文件的行为和映射规则。这些配置包括数据库...
3. **逆向工程(Hibernate Reverse Engineering)**:选中要映射的数据库表,右键选择`Hibernate Reverse Engineering`,这是MyEclipse提供的将数据库表转换为Hibernate映射文件和实体类的工具。 4. **配置生成选项...
当我们说“自定义字段”,通常是指领域对象中的一些特殊属性,这些属性可能无法直接通过标准的数据类型来表示,比如日期范围、地理位置等。这时,我们需要创建自定义的Hibernate类型来处理这些特殊的字段。 创建...
属性包括`name`(Java属性名)、`column`(数据库列名)、`type`(数据类型,如`integer`、`string`等)。 5. ****:一对多关系映射,表示一个实体类的某个属性引用了另一个实体类的一个实例。 6. ****:多对一...
- **`type`**:指定数据类型。 - **`not-null`**:是否不允许为空。 - **`unique`**:是否唯一。 - **`insert`**:是否参与插入操作,默认为`true`。 - **`update`**:是否参与更新操作,默认为`true`。 - **`...
**Hibernate映射详解** 在Java世界中,关系型数据库与对象模型之间的转换一直是开发中的一个挑战。Hibernate,作为一款强大的对象关系映射(ORM)框架,有效地解决了这个问题。本篇文章将深入探讨Hibernate映射的...
在Java世界中,Hibernate是一个强大的对象关系映射(ORM)框架,它允许开发者将数据库操作转化为对Java对象的操作,极大地简化了数据访问层的编程。"hibernate 映射"是这个框架的核心概念之一,涉及到如何将数据库表...
在使用Middlegen时,开发者需要注意的是,虽然自动化工具能减轻工作量,但生成的XML映射文件可能需要根据实际需求进行调整,例如添加自定义的属性或者处理复杂的数据类型和关系。此外,随着技术的发展,许多现代ORM...
然而,当我们与数据库进行交互,特别是使用ORM(对象关系映射)框架如Hibernate时,这些数据类型需要与数据库中对应的数据类型相匹配,以确保数据的正确存储和检索。下面我们将详细探讨Java、Hibernate以及SQL之间的...
本文将深入探讨如何在Hibernate中调用Oracle的函数,以实现高效的数据操作。 首先,我们需要理解Hibernate的核心理念,它允许开发者通过面向对象的方式来处理数据库操作,而无需编写大量的SQL语句。Hibernate通过...
在Hibernate中映射枚举类型是一个常见的需求,利用好Hibernate提供的工具和自定义映射器可以让我们更加灵活地处理不同场景下的枚举类型映射需求。通过本文介绍的方法,我们可以轻松地将枚举类型的`name`、`ordinal`...
例如,达梦Hibernate方言会包含对达梦特有的数据类型、函数和存储过程的适配。 对于“达梦Hibernate方言2.0至4.0”,这意味着该方言支持Hibernate框架从2.0到4.0的多个版本。每个新版本的Hibernate都可能引入新的...
在使用Hibernate进行数据库操作时,有时会遇到一个常见的问题,即当从数据库中查询Date类型的数据并由Hibernate返回时,发现结果中的时分秒部分不正确。这个问题通常源于多个因素,包括日期时间的序列化与反序列化...