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

Hibernate高级映射技术(二)自定义数据类型StringMap(转)相关推荐

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

    转载于:http://ajava.org/course/open/14004.html 核心提示:上一篇文章介绍了数据库中用;分隔的字段的一种方便的高级映射自定义数据类型StringList.这次是我 ...

  2. Hibernate高级映射技术(一)自定义数据类型StringList (转载用于收藏)

    转载于:http://ajava.org/course/open/14003.html 核心提示:我们在设计数据库时往往会遇到例如用户的多个手机号码的一对多问题,如果设计一个T_MOBILE表保存未免 ...

  3. Hibernate高级映射技术(一)自定义数据类型StringList (转)

    核心提示:我们在设计数据库时往往会遇到例如用户的多个手机号码的一对多问题,如果设计一个T_MOBILE表保存未免太大动干戈而且影响速度,所以如果没有严格的要求,一般情况我们在T_USER表里设计一个 ...

  4. hibernate 高级映射 --张国亮总结第一季

    在做持久化类的时候的规定: 1).有一个默认的构造方法: 2).所有的属性都有setter和getter方法 3).有一个对象标识符Oid; 4).如果有集合属性,则必须定义成接口类型:List.Se ...

  5. hibernate的映射之二(一对多双向关联)

    hibernate的一对多双关联 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 hihernate一对多关联映射(双向Dept<----->Emp) 一对多双 ...

  6. 480集课程-打通Python开发的任督二脉 轻松掌握Python高级开发技术 Python超级学科课程

    480集课程-打通Python开发的任督二脉 轻松掌握Python高级开发技术 Python超级学科课程 ===============课程目录=============== ├─(1) 01-Pyt ...

  7. RHEL6.3 DNS高级技术二 通过DNS主从区域复制实现DNS View负载均衡和冗余备份

    RHEL6.3 DNS高级技术二 ----通过DNS主从区域复制实现DNS View负载均衡和冗余备份 版权声明: 本文遵循"署名非商业性使用相同方式共享 2.5 中国大陆"协议 ...

  8. mybatis高级映射多对多查询(二)

    在这篇博客中,我来介绍下mybatis中的多对多查询的案例,在mybatis中,如何使用ResultMap来实现多对多的查询? 案例:一个user可以有很多role,一个role可以有很多entitl ...

  9. 有限元matlab_“ANSYS APDL有限元高级分析技术与二次开发”研修班

        课程背景 APDL参数化设计语言,作为ANSYS Mechanical高级分析技术之一,是ANSYS高级用户不可或缺的应用技术之一.为提高广大学员利用ANSYS软件解决实际工程问题的能力,宏新 ...

最新文章

  1. 四种排序(冒泡、插入、递归、选择)
  2. 理解Tomcat架构、启动流程及其性能优化
  3. wps怎么做时间线_妈妈忙碌没时间给娃做辅食怎么办?试试这道辅食,快手还营养...
  4. ajax实现翻书效果,jQuery实现手机版页面翻页效果的简单实例
  5. 拒绝offer的理由_接受拒绝的3大理由
  6. 如果看了此文你还不懂傅里叶变换,那就过来掐死我吧【完整版】(ZZ伯乐在线)...
  7. Jan 09 - Count Primes; Mathematics; Optimization; Primes; DP;
  8. php正则说明,php正则说明
  9. php 投票评选插件,jQuery_投票系统显示结果--jQuery插件,投票系统是网站中十分常见的 - phpStudy...
  10. Report Machine 在WIN7系统下 IE里面运行错误
  11. python连接微信运动_怎样读取微信运动数据接口?
  12. 高中计算机教育类文章,高中信息技术的教学论文
  13. 开始学习英语的七个步骤。
  14. vscode运行命令是报错:标记“”不是此版本中的有效语句分隔符。
  15. 官网下载VMware Workstation Player 16、15、14
  16. 关于“显示器驱动程序已停止响应并且已成功恢复”的解决方案
  17. 淘宝信誉查询软件 官网免费版
  18. JavaConfig+springboot入门
  19. Power Apps Android APK(v3.22081.11)下载
  20. 必应词典win10问题

热门文章

  1. 深度共情:让人际交往和沟通变得高效自在
  2. 【Class 19】【实例】python 爬虫简单案例实现
  3. Kylin环境搭建(保姆级教程)
  4. AcWing周赛 72 场 LeetCode单周赛 314 场 总结
  5. git安装与使用详细讲解
  6. 网易邮箱批量登泉器v1.0
  7. 01组团队项目-Beta冲刺-3/5
  8. MIT 6.828 学习笔记4 Lab2实验报告
  9. zoj 1002 Fire Net 碉堡的最大数量【DFS】
  10. WLAN室内、室外无线信号覆盖解决方案