转载于:http://ajava.org/course/open/14003.html
核心提示:我们在设计数据库时往往会遇到例如用户的多个手机号码的一对多问题,如果设计一个T_MOBILE表保存未免太大动干戈而且影响速度,所以如果没有严格的要求,一般情况我们在T_USER表里设计一个mobiles字段,其中的多个手机号码用;分隔。尽管这样不符合数据库范式
我们在设计数据库时往往会遇到例如用户的多个手机号码的一对多问题,如果设计一个T_MOBILE表保存未免太大动干戈而且影响速度,所以如果没有严格的要求,一般情况我们在T_USER表里设计一个mobiles字段,其中的多个手机号码用;分隔。尽管这样不符合数据库范式的设计原则,但在性能和编码复杂度上确实最低的。
这样如果用Hibernate的String类型来映射,就会得到一个长字符串,每次必须按;分隔后才能使用,这样代码就很冗余。
幸好Hibernate有自定义数据类型的支持,只要实现UserType或CompositeUserType接口。不过这两个接口的内容比较复杂,有很多方法需要实现,不能偷懒哦:-)
下 面是我对于用;分隔的字段的自定义数据类型的实现。
package com.willishz.framework.dao.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.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
/**
* 用分隔符分隔的字符串数组.分隔符默认为";"
* @author willishz
*/
public class StringList implements UserType, Serializable {
public StringList() {
super();
}
public StringList(char splitter) {
super();
this.splitter = splitter;
}
public StringList(List<String> attributeList) {
super();
this.attributeList = attributeList;
}
private List<String> attributeList;
/**
* 分隔符
*/
private char splitter = SPLITTER;
/**
* 分隔符默认为";"
*/
private static final char SPLITTER = ';';
private static final int[] SQLTYPES = new int[] { Types.VARCHAR };
public boolean isMutable() {
return false;
}
public int[] sqlTypes() {
return SQLTYPES;
}
public Object assemble(Serializable id, Object obj) throws HibernateException {
return null;
}
/**
* 将List类型的数组拼接成字符串
* @param attributeList
* @return
* @throws HibernateException
*/
public Object assemble(List<String> attributeList) throws HibernateException {
if (attributeList == null) {
return null;
}
StringBuffer asbl = new StringBuffer();
asbl.append(attributeList.get(0));
for (int i = 1; i < attributeList.size(); i++) {
asbl.append(splitter).append(attributeList.get(i));
}
return asbl.toString();
}
/**
* 自定义类型的完全复制方法,返回一个和原自定义数据相同的新对象
*
* @param value the object to be cloned, which may be null
* @return Object a copy
* @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object)
*/
public Object deepCopy(Object value) throws HibernateException {
if (value == null) {
return null;
}
ArrayList sourceList = (ArrayList) value;
ArrayList targetList = new ArrayList();
List<String> _attributeList = new ArrayList<String>();
targetList.addAll(sourceList);
return targetList;
}
/**
* 自定义数据类型的比较方法
*
* @param x
* @param y
* @return boolean
* @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object)
*/
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true;
}
if (x != null && y != null) {
List<String> xList = (List<String>) x;
List<String> yList = (List<String>) y;
if (xList.size() != yList.size()) {
return false;
}
String _x = null;
String _y = null;
for (int i = 0; i < xList.size(); i++) {
_x = xList.get(i);
_y = yList.get(i);
if (!_x.equalsIgnoreCase(_y)) { // case insensitive
return false;
}
}
return true;
}
return false;
}
public int hashCode(Object arg0) throws HibernateException {
return attributeList.hashCode();
}
/**
* 将以分隔符分隔的字符串解析成一个字符串数组
*
* @param value
* @return
*/
public List<String> parse(String value) {
if (value == null) {
return null;
}
String[] strs = org.apache.commons.lang.StringUtils.split(value, splitter);
List<String> attributeList = new ArrayList<String>();
for (int i = 0; i < strs.length; i++) {
attributeList.add(strs[i]);
}
return attributeList;
}
/**
* 从JDBC的ResultSet中读取数据,并将其转换为自定义类型后返回。
* 此方法要求对可能出现null的情况做处理。
* names中包含了当前自定义类型的映射字段名称。
*
* @param rs a JDBC result set
* @param names the column names
* @param owner the containing entity
* @return Object
* @throws HibernateException
* @throws SQLException
* @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
*/
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);
}
return null;
}
/**
* 在Hibernate进行数据保存时被调用
* 可以通过PreparedStatement将自定义数据写入对应的数据库字段中
* names中包含了当前自定义类型的映射字段名称。
*
* @param st a JDBC prepared statement
* @param value the object to write
* @param index statement parameter index
* @throws HibernateException
* @throws SQLException
* @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
*/
public void nullSafeSet(PreparedStatement pst, Object value, int index)
throws HibernateException, SQLException {
if (value != null) {
Hibernate.STRING.nullSafeSet(pst, assemble((List<String>) value), index);
} else {
Hibernate.STRING.nullSafeSet(pst, value, index);
}
}
public Class returnedClass() {
return StringList.class;
}
public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
return null;
}
public Serializable disassemble(Object arg0) throws HibernateException {
return null;
}
}
Hibernate配置文件的相关内容如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.willishz.apocalypse.ebid.domain">
<class
name="User"
table="t_user"
>
.................
<property
name="mobiles"
column="mobiles"
type="com.willishz.framework.dao.usertype.StringList"
not-null="false"
length="100"
/>
.................
</class>
</hibernate-mapping>
Hibernate映射实体文件的相关内容:
package com.willishz.apocalypse.ebid.domain.base;
import java.io.Serializable;
public abstract class User implements Serializable {
.................
private java.util.List<String> mobiles;
public java.util.List<String> getMobiles() {
return mobiles;
}
public void setmobiles(java.util.List<String> mobiles) {
this.mobiles = mobiles;
}
.................
}
分享到:
相关推荐
此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...
`hibernate-mapping`节点是Hibernate映射文件中的顶级节点,用于定义一系列配置选项,控制整个映射文件的行为和映射规则。这些配置包括数据库连接细节、默认的映射策略等。 - **schema**: 定义了数据库的Schema名称...
属性包括`name`(Java属性名)、`column`(数据库列名)、`type`(数据类型,如`integer`、`string`等)。 5. ****:一对多关系映射,表示一个实体类的某个属性引用了另一个实体类的一个实例。 6. ****:多对一...
在Java的持久化技术中,Hibernate是一个非常重要的ORM(对象关系映射)框架,它允许开发者用面向对象的方式来处理数据库操作。本篇文章主要探讨的是Hibernate中对象与数据库表之间的集合映射,这是Hibernate实现对象...
本文主要聚焦于Hibernate框架下的集合映射机制,特别是针对`Set`、`List`、`Array`、`Map`、`Bag`五种集合类型的映射进行深入探讨。通过具体的代码示例和XML配置文件,帮助读者理解如何在Hibernate中正确地配置这些...
Hibernate允许开发者自定义数据类型,将复杂对象如集合转化为字符串存储。这通常涉及到实现`UserType`接口,覆盖其中的方法如`sqlTypes()`、`returnedClass()`等。自定义类型可以用于处理非标准数据库字段,如存储...
在Java的持久化框架中,Hibernate是一个非常重要的工具,它提供了强大的对象关系映射(ORM)功能,使得开发者可以方便地在Java对象和数据库表之间进行数据操作。当我们需要执行一些特殊的、复杂的或者非标准的SQL...
1. **ORM 映射**:Hibernate 支持多种映射策略,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。这些映射方式使得对象模型与数据库之间的转换更加灵活和高效。 ...
- **原因**: 默认情况下,Hibernate 会将 `char` 类型的字段映射为 `String` 类型,而不是 `Character` 或其他字符类型的包装类。 ##### 3. 查询参数绑定问题 - **问题**: 在使用 HQL 或者 Native SQL 查询时,...
首先,Hibernate是一个流行的Java ORM(对象关系映射)框架,它提供了一种将Java对象与数据库表之间的映射方式,使得开发者可以使用面向对象的方式来操作数据库,而无需关注底层SQL语句的编写。利用Hibernate,我们...
在Java开发领域,SSH(Struts、Spring、Hibernate)是一个非常经典的Web应用程序开发框架,其中Hibernate作为持久层框架,负责对象关系映射(ORM)。在Hibernate中,XML配置文件是连接对象模型与数据库模型的关键,...
在Java的持久化框架Hibernate中,开发者经常需要根据特定需求查询数据库,并将查询结果映射到自定义的对象上,这通常涉及到使用HQL(Hibernate Query Language)或原生SQL(Native SQL)。本篇将深入探讨如何在...
而Hibernate注解则是其在ORM(对象关系映射)领域的进一步进化,它允许开发者将元数据直接嵌入到Java类和属性的声明中,从而避免了XML配置文件的繁琐。本篇将详细阐述Hibernate注解的相关知识。 一、Hibernate注解...
Hibernate还支持一对多、多对一、一对一、多对多的关系映射,懒加载、级联操作、延迟加载等高级特性,以及自定义类型和事件监听器。 9. 实战应用 通过实际项目案例,如用户管理系统、订单系统等,深入理解...
POJO,即“简单的老式Java对象”,是Hibernate中用来映射数据库表的一个核心概念。POJO通常遵循JavaBean规范,具有getter和setter方法,用于封装数据和提供访问操作。在Hibernate中,POJO的作用是将数据库表中的记录...
5. `@Column`: 定义字段在数据库表中的列名、数据类型、长度等属性。 ```java @Column(name = "username", length = 50, nullable = false) private String username; ``` **三、关系映射注解** 6. `@OneToOne`: ...
7. **其他注解**:还包括`@Temporal`(时间戳类型)、`@Lob`(大对象处理)、`@Temporal`(日期和时间类型处理)等,提供了对特殊数据类型的处理。 总之,`hibernate-annotations-3.4.0.jar`是Hibernate ORM的重要...
在SSH(Spring、Struts2、Hibernate)框架中,我们经常需要处理各种数据结构,比如集合List,并将这些数据转化为JSON格式以便于前端展示或进行API交互。JSON(JavaScript Object Notation)是一种轻量级的数据交换...
- 映射基本类型或值类型的集合,如List<String>。 - **双向关联:** - 建立两个实体间的双向关联,并确保两边的关联信息保持一致。 - **使双向连起来:** - 如何通过适当的映射策略来维护这种一致性。 - **第...
在Hibernate中,标签(Annotations)是用于定义对象与数据库表之间的映射关系的一种方式,它们直接在类或属性上进行注解,使得代码更简洁、易读。本文将详细介绍Hibernate中的主要标签及其用法。 1. **@Entity** ...