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.packagecom.willishz.framework.dao.usertype;
2.
3.importjava.io.Serializable;
4.importjava.sql.PreparedStatement;
5.importjava.sql.ResultSet;
6.importjava.sql.SQLException;
7.importjava.sql.Types;
8.importjava.util.ArrayList;
9.importjava.util.Collections;
10.importjava.util.HashMap;
11.importjava.util.Iterator;
12.importjava.util.List;
13.importjava.util.Map;
14.
15.importorg.apache.commons.collections.map.LinkedMap;
16.importorg.hibernate.Hibernate;
17.importorg.hibernate.HibernateException;
18.importorg.hibernate.usertype.UserType;
19.
20./**
21.*格式为{key:value};{key:value1,value2}的字符串数组.
22.*@authorwillishz
23.*/
24.publicclassStringMapimplementsUserType,Serializable{
25.
26.publicStringMap(){
27.super();
28.}
29.
30.publicStringMap(MapattributeMap){
31.super();
32.this.attributeMap=attributeMap;
33.}
34.
35.privateMapattributeMap;
36.
37.publicstaticfinalStringSPLITTER=";";
38.
39.publicstaticfinalStringSEPARATOR=":";
40.
41.publicstaticfinalStringVALUE_BREAK=",";
42.
43.publicstaticfinalcharBRACKET_LEFT='{';
44.
45.publicstaticfinalcharBRACKET_RIGHT='}';
46.
47.publicstaticfinalint[]SQLTYPES=newint[]{Types.VARCHAR};
48.
49.publicbooleanisMutable(){
50.returnfalse;
51.}
52.
53.publicint[]sqlTypes(){
54.returnSQLTYPES;
55.}
56.
57.publicObjectassemble(Serializableid,Objectobj)throwsHibernateException{
58.returnnull;
59.}
60.
61./**
62.*将Map类型的属性拼接成字符串
63.*@paramattributeList
64.*@return
65.*@throwsHibernateException
66.*/
67.publicObjectassemble(MapattributeMap)throwsHibernateException{
68.if(attributeMap==null){
69.returnnull;
70.}
71.StringBufferasbl=newStringBuffer();
72.Iteratoritr=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.returnasbl.toString().replaceFirst(SPLITTER,"");
79.}
80.
81./**
82.*自定义类型的完全复制方法,返回一个和原自定义数据相同的新对象
83.*
84.*@paramvaluetheobjecttobecloned,whichmaybenull
85.*@returnObjectacopy
86.*@seeorg.hibernate.usertype.UserType#deepCopy(java.lang.Object)
87.*/
88.publicObjectdeepCopy(Objectvalue)throwsHibernateException{
89.if(value==null){
90.returnnull;
91.}
92.MapsourceMap=(Map)value;
93.MaptargetMap=newHashMap();
94.targetMap.putAll(sourceMap);
95.returntargetMap;
96.}
97.
98./**
99.*自定义数据类型的比较方法
100.*
101.*@paramx
102.*@paramy
103.*@returnboolean
104.*@seeorg.hibernate.usertype.UserType#equals(java.lang.Object,java.lang.Object)
105.*/
106.publicbooleanequals(Objectx,Objecty)throwsHibernateException{
107.if(x==y){
108.returntrue;
109.}
110.if(x!=null&&y!=null){
111.MapxMap=(Map)x;
112.MapyMap=(Map)y;
113.if(xMap.size()!=yMap.size()){
114.returnfalse;
115.}
116.List<String>_xList=newArrayList(xMap.keySet());
117.List<String>_yList=newArrayList(xMap.keySet());
118.Collections.sort(_xList);
119.Collections.sort(_yList);
120.for(inti=0;i<xMap.size();i++){
121.if(!_xList.get(i).equals(_yList.get(i))){
122.returnfalse;
123.}
124.if(!xMap.get(_xList.get(i)).equals(yMap.get(_yList.get(i)))){
125.returnfalse;
126.}
127.}
128.returntrue;
129.}
130.returnfalse;
131.}
132.
133.publicinthashCode(Objectarg0)throwsHibernateException{
134.returnattributeMap.hashCode();
135.}
136.
137./**
138.*将以格式为{key:value};{key:value1,value2}的字符串数组解析成一个Map
139.*
140.*@paramvalue
141.*@return
142.*/
143.publicMapparse(Stringvalue){
144.if(value==null){
145.returnnull;
146.}
147.String[]strs=org.apache.commons.lang.StringUtils.split(value.trim(),SPLITTER);
148.MapattributeMap=newLinkedMap();
149.String_temp=null;
150.for(inti=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.returnattributeMap;
155.}
156.
157./**
158.*从JDBC的ResultSet中读取数据,并将其转换为自定义类型后返回。
159.*此方法要求对可能出现null的情况做处理。
160.*names中包含了当前自定义类型的映射字段名称。
161.*
162.*@paramrsaJDBCresultset
163.*@paramnamesthecolumnnames
164.*@paramownerthecontainingentity
165.*@returnObject
166.*@throwsHibernateException
167.*@throwsSQLException
168.*@seeorg.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,java.lang.String[],java.lang.Object)
169.*/
170.publicObjectnullSafeGet(ResultSetrs,String[]names,Objectowner)
171.throwsHibernateException,SQLException{
172.Stringvalue=(String)Hibernate.STRING.nullSafeGet(rs,names[0]);
173.if(value!=null){
174.attributeMap=parse(value);
175.returnattributeMap;
176.}
177.returnnull;
178.}
179.
180./**
181.*在Hibernate进行数据保存时被调用
182.*可以通过PreparedStatement将自定义数据写入对应的数据库字段中
183.*names中包含了当前自定义类型的映射字段名称。
184.*
185.*@paramstaJDBCpreparedstatement
186.*@paramvaluetheobjecttowrite
187.*@paramindexstatementparameterindex
188.*@throwsHibernateException
189.*@throwsSQLException
190.*@seeorg.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,java.lang.String[],java.lang.Object)
191.*/
192.publicvoidnullSafeSet(PreparedStatementpst,Objectvalue,intindex)
193.throwsHibernateException,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.publicClassreturnedClass(){
202.returnStringMap.class;
203.}
204.
205.publicObjectreplace(Objectarg0,Objectarg1,Objectarg2)throwsHibernateException{
206.returnnull;
207.}
208.
209.publicSerializabledisassemble(Objectarg0)throwsHibernateException{
210.returnnull;
211.}
212.
213.publicMapgetAttributeMap(){
214.returnattributeMap;
215.}
216.
217.publicvoidsetAttributeMap(MapattributeMap){
218.this.attributeMap=attributeMap;
219.}
220.}
221.
222.
Hibernate配置文件的相关内容如下:
1.<?xmlversion="1.0"?>
2.<!DOCTYPEhibernate-mappingPUBLIC
3."-//Hibernate/HibernateMappingDTD//EN"
4."http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5.
6.<hibernate-mappingpackage="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.packagecom.willishz.apocalypse.ebid.domain.base;
2.
3.importjava.io.Serializable;
4.
5.publicabstractclassUserimplementsSerializable{
6..................
7.
8.privatejava.util.Mapspecification;
9.
10./**
11.*Returnthevalueassociatedwiththecolumn:specification
12.*/
13.publicjava.util.MapgetSpecification(){
14.returnspecification;
15.}
16.
17./**
18.*Setthevaluerelatedtothecolumn:specification
19.*@paramspecificationthespecificationvalue
20.*/
21.publicvoidsetSpecification(java.util.Mapspecification){
22.this.specification=specification;
23.}
24.
25..................
26.}