Hibernate高级映射技术(二)自定义数据类型StringMap

    核心提示:上一篇文章介绍了数据库中用;分隔的字段的一种方便的高级映射自定义数据类型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}的字符串数组的自定义数据类型的实现。

       1. package com.willishz.framework.dao.usertype;  
       2.  
       3. import java.io.Serializable;  
       4. import java.sql.PreparedStatement;  
       5. import java.sql.ResultSet;  
       6. import java.sql.SQLException;  
       7. import java.sql.Types;  
       8. import java.util.ArrayList;  
       9. import java.util.Collections;  
      10. import java.util.HashMap;  
      11. import java.util.Iterator;  
      12. import java.util.List;  
      13. import java.util.Map;  
      14.  
      15. import org.apache.commons.collections.map.LinkedMap;  
      16. import org.hibernate.Hibernate;  
      17. import org.hibernate.HibernateException;  
      18. import org.hibernate.usertype.UserType;  
      19.  
      20. /** 
      21.  * 格式为{key:value};{key:value1,value2}的字符串数组. 
      22.  * @author willishz 
      23.  */ 
      24. public class StringMap implements UserType, Serializable {  
      25.  
      26.  public StringMap() {  
      27.   super();  
      28.  }  
      29.  
      30.  public StringMap(Map attributeMap) {  
      31.   super();  
      32.   this.attributeMap = attributeMap;  
      33.  }  
      34.  
      35.  private Map attributeMap;  
      36.  
      37.  public static final String SPLITTER = ";";  
      38.  
      39.  public static final String SEPARATOR = ":";  
      40.  
      41.  public static final String VALUE_BREAK = ",";  
      42.  
      43.  public static final char BRACKET_LEFT = '{';  
      44.  
      45.  public static final char BRACKET_RIGHT = '}';  
      46.  
      47.  public static final int[] SQLTYPES = new int[] { Types.VARCHAR };  
      48.  
      49.  public boolean isMutable() {  
      50.   return false;  
      51.  }  
      52.  
      53.  public int[] sqlTypes() {  
      54.   return SQLTYPES;  
      55.  }  
      56.  
      57.  public Object assemble(Serializable id, Object obj) throws HibernateException {  
      58.   return null;  
      59.  }  
      60.  
      61.  /** 
      62.   * 将Map类型的属性拼接成字符串 
      63.   * @param attributeList 
      64.   * @return 
      65.   * @throws HibernateException 
      66.   */ 
      67.  public Object assemble(Map attributeMap) throws HibernateException {  
      68.   if (attributeMap == null) {  
      69.    return null;  
      70.   }  
      71.   StringBuffer asbl = new StringBuffer();  
      72.   Iterator itr = attributeMap.keySet().iterator();  
      73.   String _key = null;  
      74.   while (itr.hasNext()) {  
      75.    _key = (String) itr.next();  
      76.    asbl.append(SPLITTER).append(BRACKET_LEFT).append(_key).append(SEPARATOR).append(attributeMap.get(_key)).append(BRACKET_RIGHT);  
      77.   }  
      78.   return asbl.toString().replaceFirst(SPLITTER, "");  
      79.  }  
      80.  
      81.  /** 
      82.   * 自定义类型的完全复制方法,返回一个和原自定义数据相同的新对象 
      83.   * 
      84.   * @param value the object to be cloned, which may be null 
      85.   * @return Object a copy 
      86.   * @see org.hibernate.usertype.UserType#deepCopy(java.lang.Object) 
      87.   */ 
      88.  public Object deepCopy(Object value) throws HibernateException {  
      89.   if (value == null) {  
      90.    return null;  
      91.   }  
      92.   Map sourceMap = (Map) value;  
      93.   Map targetMap = new HashMap();  
      94.   targetMap.putAll(sourceMap);  
      95.   return targetMap;  
      96.  }  
      97.  
      98.  /** 
      99.   * 自定义数据类型的比较方法 
     100.   *  
     101.   * @param x 
     102.   * @param y 
     103.   * @return boolean 
     104.   * @see org.hibernate.usertype.UserType#equals(java.lang.Object, java.lang.Object) 
     105.   */ 
     106.  public boolean equals(Object x, Object y) throws HibernateException {  
     107.   if (x == y) {  
     108.    return true;  
     109.   }  
     110.   if (x != null && y != null) {  
     111.    Map xMap = (Map) x;  
     112.    Map yMap = (Map) y;  
     113.    if (xMap.size() != yMap.size()) {  
     114.     return false;  
     115.    }  
     116.    List<String> _xList = new ArrayList(xMap.keySet());  
     117.    List<String> _yList = new ArrayList(xMap.keySet());  
     118.    Collections.sort(_xList);  
     119.    Collections.sort(_yList);  
     120.    for (int i = 0; i < xMap.size(); i++) {  
     121.     if (!_xList.get(i).equals(_yList.get(i))) {  
     122.      return false;  
     123.     }  
     124.     if (!xMap.get(_xList.get(i)).equals(yMap.get(_yList.get(i)))) {  
     125.      return false;  
     126.     }  
     127.    }  
     128.    return true;  
     129.   }  
     130.   return false;  
     131.  }  
     132.  
     133.  public int hashCode(Object arg0) throws HibernateException {  
     134.   return attributeMap.hashCode();  
     135.  }  
     136.  
     137.  /** 
     138.   * 将以格式为{key:value};{key:value1,value2}的字符串数组解析成一个Map 
     139.   *  
     140.   * @param value 
     141.   * @return 
     142.   */ 
     143.  public Map parse(String value) {  
     144.   if (value == null) {  
     145.    return null;  
     146.   }  
     147.   String[] strs = org.apache.commons.lang.StringUtils.split(value.trim(), SPLITTER);  
     148.   Map attributeMap = new LinkedMap();  
     149.   String _temp = null;  
     150.   for (int i = 0; i < strs.length; i++) {  
     151.    _temp = strs[i].substring(1, strs[i].length() - 1);  
     152.    attributeMap.put(_temp.split(SEPARATOR, 2)[0], _temp.split(SEPARATOR, 2)[1]);  
     153.   }  
     154.   return attributeMap;  
     155.  }  
     156.  
     157.  /** 
     158.   * 从JDBC的ResultSet中读取数据,并将其转换为自定义类型后返回。 
     159.   * 此方法要求对可能出现null的情况做处理。 
     160.   * names中包含了当前自定义类型的映射字段名称。 
     161.   *  
     162.   * @param rs a JDBC result set 
     163.   * @param names the column names 
     164.   * @param owner the containing entity 
     165.   * @return Object 
     166.   * @throws HibernateException 
     167.   * @throws SQLException 
     168.   * @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object) 
     169.   */ 
     170.  public Object nullSafeGet(ResultSet rs, String[] names, Object owner)  
     171.  throws HibernateException, SQLException {  
     172.   String value = (String) Hibernate.STRING.nullSafeGet(rs, names[0]);  
     173.   if (value != null) {  
     174.    attributeMap = parse(value);  
     175.    return attributeMap;  
     176.   }  
     177.   return null;  
     178.  }  
     179.  
     180.  /** 
     181.   * 在Hibernate进行数据保存时被调用 
     182.   * 可以通过PreparedStatement将自定义数据写入对应的数据库字段中 
     183.   * names中包含了当前自定义类型的映射字段名称。 
     184.   * 
     185.   * @param st a JDBC prepared statement 
     186.   * @param value the object to write 
     187.   * @param index statement parameter index 
     188.   * @throws HibernateException 
     189.   * @throws SQLException 
     190.   * @see org.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object) 
     191.   */ 
     192.  public void nullSafeSet(PreparedStatement pst, Object value, int index)  
     193.  throws HibernateException, SQLException {  
     194.   if (value != null) {  
     195.    Hibernate.STRING.nullSafeSet(pst, assemble((Map) value), index);  
     196.   } else {  
     197.    Hibernate.STRING.nullSafeSet(pst, value, index);  
     198.   }  
     199.  }  
     200.  
     201.  public Class returnedClass() {  
     202.   return StringMap.class;  
     203.  }  
     204.  
     205.  public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {  
     206.   return null;  
     207.  }  
     208.  
     209.  public Serializable disassemble(Object arg0) throws HibernateException {  
     210.   return null;  
     211.  }  
     212.  
     213.  public Map getAttributeMap() {  
     214.   return attributeMap;  
     215.  }  
     216.  
     217.  public void setAttributeMap(Map attributeMap) {  
     218.   this.attributeMap = attributeMap;  
     219.  }  
     220. }  
     221.  
     222.   

    Hibernate配置文件的相关内容如下:

       1. <?xml version="1.0"?> 
       2. <!DOCTYPE hibernate-mapping PUBLIC  
       3.  "-//Hibernate/Hibernate Mapping DTD//EN"  
       4.  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > 
       5.  
       6. <hibernate-mapping package="com.willishz.apocalypse.ebid.domain"> 
       7.  <class 
       8.   name="Merchandise" 
       9.   table="t_merchandise" 
      10.   lazy="false" 
      11.  > 
      12.  .................  
      13.   <property 
      14.    name="specification" 
      15.    column="specification" 
      16.    type="com.willishz.framework.dao.usertype.StringMap" 
      17.    not-null="false" 
      18.   /> 
      19.  .................  
      20.  </class>   
      21. </hibernate-mapping> 

    Hibernate映射实体文件的相关内容:

       1. package com.willishz.apocalypse.ebid.domain.base;  
       2.  
       3. import java.io.Serializable;  
       4.  
       5. public abstract class User  implements Serializable {  
       6.  .................  
       7.    
       8.  private java.util.Map specification;  
       9.  
      10.  /** 
      11.   * Return the value associated with the column: specification 
      12.   */ 
      13.  public java.util.Map getSpecification () {  
      14.   return specification;  
      15.  }  
      16.  
      17.  /** 
      18.   * Set the value related to the column: specification 
      19.   * @param specification the specification value 
      20.   */ 
      21.  public void setSpecification (java.util.Map specification) {  
      22.   this.specification = specification;  
      23.  }  
      24.  
      25.  .................  
      26. } 

你可能感兴趣的:(java,数据结构,sql,Hibernate,jdbc)