`
gqzyyxh
  • 浏览: 9643 次
  • 性别: Icon_minigender_1
  • 来自: 常州
文章分类
社区版块
存档分类
最新评论

Hibernate高级映射技术(二)自定义数据类型StringMap (转载用于收藏)

阅读更多
转载于: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;   
}   
  
.................   
}  
分享到:
评论

相关推荐

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

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

    常用 Hibernate 映射配置说明.doc

    ### 常用Hibernate映射配置详解 #### 1. hibernate-mapping节点解析 `hibernate-mapping`节点是Hibernate映射文件中的顶级节点,用于定义一系列配置选项,控制整个映射文件的行为和映射规则。这些配置包括数据库...

    Hibernate 映射文件 结构

    属性包括`name`(Java属性名)、`column`(数据库列名)、`type`(数据类型,如`integer`、`string`等)。 5. ****:一对多关系映射,表示一个实体类的某个属性引用了另一个实体类的一个实例。 6. ****:多对一...

    hibernate集合的映射

    对于复杂的集合映射,我们还可以自定义映射类,通过实现Hibernate的`CollectionType`接口,来提供更灵活的数据结构和行为。 总结来说,Hibernate的集合映射是连接对象模型与关系数据库的重要桥梁,理解并熟练掌握其...

    JAVA培训-HIBERNATE的集合映射.doc

    本文主要聚焦于Hibernate框架下的集合映射机制,特别是针对`Set`、`List`、`Array`、`Map`、`Bag`五种集合类型的映射进行深入探讨。通过具体的代码示例和XML配置文件,帮助读者理解如何在Hibernate中正确地配置这些...

    hbm xml配置详解 ssh框架

    7. ****、****、**** 和 **&lt;map&gt;**:集合映射,对应Java的List、Set、Map等集合类型。 接下来,我们关注一下`Hibernate 映射类型`。映射类型是Hibernate实现ORM的核心,它们是Java类型和SQL类型之间的桥梁。...

    本人写的Hibernate超级通用DAO

    以及`List&lt;T&gt; findByNamedQuery(String namedQuery, Map&lt;String, Object&gt; params)`,使用预定义的命名查询。 3. **分页查询**:在大型项目中,通常需要实现分页功能,我们可以提供`List&lt;T&gt; findPage(int pageSize, ...

    Hibernate SQLQuery 本地查询

    在Java的持久化框架Hibernate中,SQLQuery是用于执行自定义SQL语句的重要工具,它允许开发者绕过ORM(对象关系映射)的抽象层,直接与数据库进行交互。这篇博客"Hibernate SQLQuery 本地查询"可能详细讲解了如何利用...

    hibernate文档

    Hibernate 是一个开源的对象关系映射 (Object-Relational Mapping, ORM) 框架,用于 Java 应用程序中的数据库访问。它提供了一种机制,可以将 Java 对象映射到数据库表,并且支持 SQL 作为查询语言。该文档为 ...

    hibernate参考文档

    映射声明覆盖了从数据类型映射到数据库表的详细配置: 1. **Doctype**:文档类型定义。 2. **hibernate-mapping**:映射文件根元素。 3. **class**:映射Java类到数据库表。 4. **id**:标识符生成策略,如**...

    对Hibernate框架的二次封装,简化对数据库的操作

    4. 异常封装:在实现类中捕获并处理可能出现的Hibernate或数据库异常,转换为自定义的异常类型。 5. 配置缓存:配置Hibernate的二级缓存,例如使用Ehcache或Redis,提升性能。 6. 查询优化:创建一个QueryHelper类,...

    hibernate annotations详解

    使用 `@Type` 注解来指定属性的数据类型。 **2.4.3.4 索引** 使用 `@Index` 注解来指定索引。 **2.4.3.5 父元素** 使用 `@Parent` 注解来表示实体是另一个实体的一部分。 **2.4.3.6 生成属性** 使用 `@...

    hibernate 注解 英文版的

    Hibernate 是一款流行的 Java 持久层框架,它通过 ORM(对象关系映射)技术将 Java 应用程序中的对象模型与数据库的关系模型之间建立桥梁,实现对象数据与关系型数据库数据之间的转换。在 Hibernate 中,可以使用 ...

    jackjson类型转换各种方法

    杰克逊(Jackson)是Java领域中广泛使用的JSON处理库,它提供了强大的功能,使得JSON与其他数据类型(如Java对象)之间的转换变得简单且高效。本文将深入探讨Jackson框架在JSON转换中的各种方法,帮助你更好地理解和...

    映射ResultSet结果

    `getColumnName`方法用于根据字段的注解或字段名获取列名,`convertValue`方法则用于处理可能出现的数据类型不匹配问题。 使用这个`ResultSetMapper`时,我们只需要提供查询结果的`ResultSet`和JavaBean的类类型,...

    Hibernate SQLQuery执行原生SQL.docx

    在Java的Hibernate框架中,有时候我们需要执行自定义的SQL查询以获取特定的数据,这时就可以使用SQLQuery接口。本文将深入探讨Hibernate如何通过SQLQuery接口执行原生SQL查询,并展示如何处理查询结果。 一、创建...

    SSH框架加Json数据类型整合Jar包

    - 动作类和结果类型:在动作类中,声明返回类型为`Map&lt;String, Object&gt;`或自定义的Java对象,然后在结果类型中指定`json`。 2. **Spring整合JSON**: - 配置Jackson或Gson库:`lib`目录可能包含`jackson-databind...

    详解Java的Hibernat框架中的Map映射与SortedMap映射

    在Java的Hibernate框架中,Map映射和SortedMap映射是两种常见的集合类型,用于处理对象之间的关联关系,特别是处理一对多(One-to-Many)和多对一(Many-to-One)关系。Hibernate是一个强大的对象关系映射(ORM)...

    自己总结的IBATIS资料

    - 支持基本数据类型作为输入参数,如String、Integer等。 17. **Map类型输入参数** - 允许使用Map作为输入参数,便于处理复杂的参数结构。 18. **ResultMap** - ResultMap用于定义查询结果映射规则,包括基本...

Global site tag (gtag.js) - Google Analytics