转载于:http://ajava.org/course/open/14004.html
核心提示:上一篇文章介绍了数据库中用;分隔的字段的一种方便的高级映射自定义数据类型StringList。这次是我做的另一种自定义数据类型StringMap。 在商品和属性的对应关系中,一个商品对应多个属性,例如一个数码相机型号对应有:像素:1000万,焦距:35-200mm,感光度
上一篇文章介绍了数据库中用;分隔的字段的一种方便的高级映射自定义数据类型StringList。这次是我做的另一种自定义数据类型StringMap。
在商品和属性的对应关系中,一个商品对应多个属性,例如一个数码相机型号对应有:像素:1000万,焦距:35-200mm,感光度:ISO100-1600,非常多而且还需要能适应随时增加新的属性,快速读取显示特别是可以检索。如果设计一个Attribute表(主键attriId,attrKey,attrValue,商品表的外键itemId)的一对多,不仅读取显示很慢,而且难以维护,特别是很难做检索,想搜ISO1600并且焦距200mm的1000万像素的相机,SQL就非常繁琐。所以一般使用将这些属性统一放到商品表的一个specification字段里,结构自已定义,我设置的结构是{key:value};{key:value1,value2}的字符串数组。这样再做刚才的检索时只要在一个表的一个字段里查询,就非常简单了!
幸好Hibernate有自定义数据类型的支持,只要实现UserType或CompositeUserType接口。不过这两个接口的内容比较复杂,有很多方法需要实现,不能偷懒哦:-)
下面是我对于用{key:value};{key:value1,value2}的字符串数组的自定义数据类型的实现。
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.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.map.LinkedMap;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
/**
* 格式为{key:value};{key:value1,value2}的字符串数组.
* @author willishz
*/
public class StringMap implements UserType, Serializable {
public StringMap() {
super();
}
public StringMap(Map attributeMap) {
super();
this.attributeMap = attributeMap;
}
private Map attributeMap;
public static final String SPLITTER = ";";
public static final String SEPARATOR = ":";
public static final String VALUE_BREAK = ",";
public static final char BRACKET_LEFT = '{';
public static final char BRACKET_RIGHT = '}';
public 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;
}
/**
* 将Map类型的属性拼接成字符串
* @param attributeList
* @return
* @throws HibernateException
*/
public Object assemble(Map attributeMap) throws HibernateException {
if (attributeMap == null) {
return null;
}
StringBuffer asbl = new StringBuffer();
Iterator itr = attributeMap.keySet().iterator();
String _key = null;
while (itr.hasNext()) {
_key = (String) itr.next();
asbl.append(SPLITTER).append(BRACKET_LEFT).append(_key).append(SEPARATOR).append(attributeMap.get(_key)).append(BRACKET_RIGHT);
}
return asbl.toString().replaceFirst(SPLITTER, "");
}
/**
* 自定义类型的完全复制方法,返回一个和原自定义数据相同的新对象
*
* @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;
}
Map sourceMap = (Map) value;
Map targetMap = new HashMap();
targetMap.putAll(sourceMap);
return targetMap;
}
/**
* 自定义数据类型的比较方法
*
* @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) {
Map xMap = (Map) x;
Map yMap = (Map) y;
if (xMap.size() != yMap.size()) {
return false;
}
List<String> _xList = new ArrayList(xMap.keySet());
List<String> _yList = new ArrayList(xMap.keySet());
Collections.sort(_xList);
Collections.sort(_yList);
for (int i = 0; i < xMap.size(); i++) {
if (!_xList.get(i).equals(_yList.get(i))) {
return false;
}
if (!xMap.get(_xList.get(i)).equals(yMap.get(_yList.get(i)))) {
return false;
}
}
return true;
}
return false;
}
public int hashCode(Object arg0) throws HibernateException {
return attributeMap.hashCode();
}
/**
* 将以格式为{key:value};{key:value1,value2}的字符串数组解析成一个Map
*
* @param value
* @return
*/
public Map parse(String value) {
if (value == null) {
return null;
}
String[] strs = org.apache.commons.lang.StringUtils.split(value.trim(), SPLITTER);
Map attributeMap = new LinkedMap();
String _temp = null;
for (int i = 0; i < strs.length; i++) {
_temp = strs[i].substring(1, strs[i].length() - 1);
attributeMap.put(_temp.split(SEPARATOR, 2)[0], _temp.split(SEPARATOR, 2)[1]);
}
return attributeMap;
}
/**
* 从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) {
attributeMap = parse(value);
return attributeMap;
}
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((Map) value), index);
} else {
Hibernate.STRING.nullSafeSet(pst, value, index);
}
}
public Class returnedClass() {
return StringMap.class;
}
public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
return null;
}
public Serializable disassemble(Object arg0) throws HibernateException {
return null;
}
public Map getAttributeMap() {
return attributeMap;
}
public void setAttributeMap(Map attributeMap) {
this.attributeMap = attributeMap;
}
}
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="Merchandise"
table="t_merchandise"
lazy="false"
>
.................
<property
name="specification"
column="specification"
type="com.willishz.framework.dao.usertype.StringMap"
not-null="false"
/>
.................
</class>
</hibernate-mapping>
Hibernate映射实体文件的相关内容:
package com.willishz.apocalypse.ebid.domain.base;
import java.io.Serializable;
public abstract class User implements Serializable {
.................
private java.util.Map specification;
/**
* Return the value associated with the column: specification
*/
public java.util.Map getSpecification () {
return specification;
}
/**
* Set the value related to the column: specification
* @param specification the specification value
*/
public void setSpecification (java.util.Map specification) {
this.specification = specification;
}
.................
}
分享到:
相关推荐
此外,自定义对象的映射是Hibernate映射中的一个重要部分。通过在实体类上使用@Entity注解,并使用@Id注解指定主键字段,可以将一个Java类映射到数据库的一张表。字段则通过@Column注解来指定列名和属性,如长度、...
### 常用Hibernate映射配置详解 #### 1. hibernate-mapping节点解析 `hibernate-mapping`节点是Hibernate映射文件中的顶级节点,用于定义一系列配置选项,控制整个映射文件的行为和映射规则。这些配置包括数据库...
属性包括`name`(Java属性名)、`column`(数据库列名)、`type`(数据类型,如`integer`、`string`等)。 5. ****:一对多关系映射,表示一个实体类的某个属性引用了另一个实体类的一个实例。 6. ****:多对一...
对于复杂的集合映射,我们还可以自定义映射类,通过实现Hibernate的`CollectionType`接口,来提供更灵活的数据结构和行为。 总结来说,Hibernate的集合映射是连接对象模型与关系数据库的重要桥梁,理解并熟练掌握其...
本文主要聚焦于Hibernate框架下的集合映射机制,特别是针对`Set`、`List`、`Array`、`Map`、`Bag`五种集合类型的映射进行深入探讨。通过具体的代码示例和XML配置文件,帮助读者理解如何在Hibernate中正确地配置这些...
7. ****、****、**** 和 **<map>**:集合映射,对应Java的List、Set、Map等集合类型。 接下来,我们关注一下`Hibernate 映射类型`。映射类型是Hibernate实现ORM的核心,它们是Java类型和SQL类型之间的桥梁。...
以及`List<T> findByNamedQuery(String namedQuery, Map<String, Object> params)`,使用预定义的命名查询。 3. **分页查询**:在大型项目中,通常需要实现分页功能,我们可以提供`List<T> findPage(int pageSize, ...
在Java的持久化框架Hibernate中,SQLQuery是用于执行自定义SQL语句的重要工具,它允许开发者绕过ORM(对象关系映射)的抽象层,直接与数据库进行交互。这篇博客"Hibernate SQLQuery 本地查询"可能详细讲解了如何利用...
Hibernate 是一个开源的对象关系映射 (Object-Relational Mapping, ORM) 框架,用于 Java 应用程序中的数据库访问。它提供了一种机制,可以将 Java 对象映射到数据库表,并且支持 SQL 作为查询语言。该文档为 ...
映射声明覆盖了从数据类型映射到数据库表的详细配置: 1. **Doctype**:文档类型定义。 2. **hibernate-mapping**:映射文件根元素。 3. **class**:映射Java类到数据库表。 4. **id**:标识符生成策略,如**...
4. 异常封装:在实现类中捕获并处理可能出现的Hibernate或数据库异常,转换为自定义的异常类型。 5. 配置缓存:配置Hibernate的二级缓存,例如使用Ehcache或Redis,提升性能。 6. 查询优化:创建一个QueryHelper类,...
使用 `@Type` 注解来指定属性的数据类型。 **2.4.3.4 索引** 使用 `@Index` 注解来指定索引。 **2.4.3.5 父元素** 使用 `@Parent` 注解来表示实体是另一个实体的一部分。 **2.4.3.6 生成属性** 使用 `@...
Hibernate 是一款流行的 Java 持久层框架,它通过 ORM(对象关系映射)技术将 Java 应用程序中的对象模型与数据库的关系模型之间建立桥梁,实现对象数据与关系型数据库数据之间的转换。在 Hibernate 中,可以使用 ...
杰克逊(Jackson)是Java领域中广泛使用的JSON处理库,它提供了强大的功能,使得JSON与其他数据类型(如Java对象)之间的转换变得简单且高效。本文将深入探讨Jackson框架在JSON转换中的各种方法,帮助你更好地理解和...
`getColumnName`方法用于根据字段的注解或字段名获取列名,`convertValue`方法则用于处理可能出现的数据类型不匹配问题。 使用这个`ResultSetMapper`时,我们只需要提供查询结果的`ResultSet`和JavaBean的类类型,...
在Java的Hibernate框架中,有时候我们需要执行自定义的SQL查询以获取特定的数据,这时就可以使用SQLQuery接口。本文将深入探讨Hibernate如何通过SQLQuery接口执行原生SQL查询,并展示如何处理查询结果。 一、创建...
- 动作类和结果类型:在动作类中,声明返回类型为`Map<String, Object>`或自定义的Java对象,然后在结果类型中指定`json`。 2. **Spring整合JSON**: - 配置Jackson或Gson库:`lib`目录可能包含`jackson-databind...
在Java的Hibernate框架中,Map映射和SortedMap映射是两种常见的集合类型,用于处理对象之间的关联关系,特别是处理一对多(One-to-Many)和多对一(Many-to-One)关系。Hibernate是一个强大的对象关系映射(ORM)...
在Java世界里,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。本篇将详细探讨Hibernate中的Criteria API,这是一种灵活且强大的查询机制,...