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}的字符串数组的自定义数据类型的实现。

packagecom.willishz.framework.dao.usertype;

importjava.io.Serializable;

importjava.sql.PreparedStatement;

importjava.sql.ResultSet;

importjava.sql.SQLException;

importjava.sql.Types;

importjava.util.ArrayList;

importjava.util.Collections;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.List;

importjava.util.Map;

importorg.apache.commons.collections.map.LinkedMap;

importorg.hibernate.Hibernate;

importorg.hibernate.HibernateException;

importorg.hibernate.usertype.UserType;

/**

*格式为{key:value};{key:value1,value2}的字符串数组.

*@authorwillishz

*/

publicclassStringMapimplementsUserType,Serializable{

publicStringMap(){

super();

}

publicStringMap(MapattributeMap){

super();

this.attributeMap=attributeMap;

}

privateMapattributeMap;

publicstaticfinalStringSPLITTER=";";

publicstaticfinalStringSEPARATOR=":";

publicstaticfinalStringVALUE_BREAK=",";

publicstaticfinalcharBRACKET_LEFT='{';

publicstaticfinalcharBRACKET_RIGHT='}';

publicstaticfinalint[]SQLTYPES=newint[]{Types.VARCHAR};

publicbooleanisMutable(){

returnfalse;

}

publicint[]sqlTypes(){

returnSQLTYPES;

}

publicObjectassemble(Serializableid,Objectobj)throwsHibernateException{

returnnull;

}

/**

*将Map类型的属性拼接成字符串

*@paramattributeList

*@return

*@throwsHibernateException

*/

publicObjectassemble(MapattributeMap)throwsHibernateException{

if(attributeMap==null){

returnnull;

}

StringBufferasbl=newStringBuffer();

Iteratoritr=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);

}

returnasbl.toString().replaceFirst(SPLITTER,"");

}

/**

*自定义类型的完全复制方法,返回一个和原自定义数据相同的新对象

*

*@paramvaluetheobjecttobecloned,whichmaybenull

*@returnObjectacopy

*@seeorg.hibernate.usertype.UserType#deepCopy(java.lang.Object)

*/

publicObjectdeepCopy(Objectvalue)throwsHibernateException{

if(value==null){

returnnull;

}

MapsourceMap=(Map)value;

MaptargetMap=newHashMap();

targetMap.putAll(sourceMap);

returntargetMap;

}

/**

*自定义数据类型的比较方法

*

*@paramx

*@paramy

*@returnboolean

*@seeorg.hibernate.usertype.UserType#equals(java.lang.Object,java.lang.Object)

*/

publicbooleanequals(Objectx,Objecty)throwsHibernateException{

if(x==y){

returntrue;

}

if(x!=null&&y!=null){

MapxMap=(Map)x;

MapyMap=(Map)y;

if(xMap.size()!=yMap.size()){

returnfalse;

}

List<String>_xList=newArrayList(xMap.keySet());

List<String>_yList=newArrayList(xMap.keySet());

Collections.sort(_xList);

Collections.sort(_yList);

for(inti=0;i<xMap.size();i++){

if(!_xList.get(i).equals(_yList.get(i))){

returnfalse;

}

if(!xMap.get(_xList.get(i)).equals(yMap.get(_yList.get(i)))){

returnfalse;

}

}

returntrue;

}

returnfalse;

}

publicinthashCode(Objectarg0)throwsHibernateException{

returnattributeMap.hashCode();

}

/**

*将以格式为{key:value};{key:value1,value2}的字符串数组解析成一个Map

*

*@paramvalue

*@return

*/

publicMapparse(Stringvalue){

if(value==null){

returnnull;

}

String[]strs=org.apache.commons.lang.StringUtils.split(value.trim(),SPLITTER);

MapattributeMap=newLinkedMap();

String_temp=null;

for(inti=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]);

}

returnattributeMap;

}

/**

*从JDBC的ResultSet中读取数据,并将其转换为自定义类型后返回。

*此方法要求对可能出现null的情况做处理。

*names中包含了当前自定义类型的映射字段名称。

*

*@paramrsaJDBCresultset

*@paramnamesthecolumnnames

*@paramownerthecontainingentity

*@returnObject

*@throwsHibernateException

*@throwsSQLException

*@seeorg.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,java.lang.String[],java.lang.Object)

*/

publicObjectnullSafeGet(ResultSetrs,String[]names,Objectowner)

throwsHibernateException,SQLException{

Stringvalue=(String)Hibernate.STRING.nullSafeGet(rs,names[0]);

if(value!=null){

attributeMap=parse(value);

returnattributeMap;

}

returnnull;

}

/**

*在Hibernate进行数据保存时被调用

*可以通过PreparedStatement将自定义数据写入对应的数据库字段中

*names中包含了当前自定义类型的映射字段名称。

*

*@paramstaJDBCpreparedstatement

*@paramvaluetheobjecttowrite

*@paramindexstatementparameterindex

*@throwsHibernateException

*@throwsSQLException

*@seeorg.hibernate.usertype.UserType#nullSafeGet(java.sql.ResultSet,java.lang.String[],java.lang.Object)

*/

publicvoidnullSafeSet(PreparedStatementpst,Objectvalue,intindex)

throwsHibernateException,SQLException{

if(value!=null){

Hibernate.STRING.nullSafeSet(pst,assemble((Map)value),index);

}else{

Hibernate.STRING.nullSafeSet(pst,value,index);

}

}

publicClassreturnedClass(){

returnStringMap.class;

}

publicObjectreplace(Objectarg0,Objectarg1,Objectarg2)throwsHibernateException{

returnnull;

}

publicSerializabledisassemble(Objectarg0)throwsHibernateException{

returnnull;

}

publicMapgetAttributeMap(){

returnattributeMap;

}

publicvoidsetAttributeMap(MapattributeMap){

this.attributeMap=attributeMap;

}

}

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

<?xmlversion="1.0"?>

<!DOCTYPEhibernate-mappingPUBLIC

"-//Hibernate/HibernateMappingDTD//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mappingpackage="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映射实体文件的相关内容:

packagecom.willishz.apocalypse.ebid.domain.base;

importjava.io.Serializable;

publicabstractclassUserimplementsSerializable{

.................

privatejava.util.Mapspecification;

/**

*Returnthevalueassociatedwiththecolumn:specification

*/

publicjava.util.MapgetSpecification(){

returnspecification;

}

/**

*Setthevaluerelatedtothecolumn:specification

*@paramspecificationthespecificationvalue

*/

publicvoidsetSpecification(java.util.Mapspecification){

this.specification=specification;

}

.................

}

相关推荐