szehnder wrote:
hello
i have to map a java.util.HashMap which does not contain elements of one type, but of different types. how do i have to map that? what sql-type is needed for object?
Code:
<map name="data" table="JOBDATA_T">
<key>
<column name="TRIGGERJOBID" sql-type="NUMBER(10)" />
</key>
<index type="object" column="KEY" />
<element type="object" column="VALUE />
</map>
using the schema gen it uses type VARCHAR2(255) for column KEY and VALUE. is this really an appropriate type for this?
thanks for your help!
You are facing a heterogeneous collection.
There are two possibilities to map it:
1) Map using <any> mapping if you don't know exact types of elements of your collection or these types are too many.
2) Homogenize your collection by introducing a superstructure for your types.
For instance, for a collection like this one:
Code:
/**
* Objects of the following type(s) are allowed in the list
* {@link test.RootType.Element2}
* {@link test.RootType.Element1}
*
*/
java.util.List getElement1AndElement2();
You may introduce the following aggregating structure:
Code:
/**
*
* @hibernate.class
*
*/
public static class Element1AndElement2Impl implements test.RootType.Element1AndElement2
{
private test.RootType.Element2 _Element2;
private test.RootType.Element1 _Element1;
private java.lang.String idInternal;
public java.lang.Object get() {
if (null!= getElement2()) {
return getElement2();
} else {
if (null!= getElement1()) {
return getElement1();
} else {
return null;
}
}
}
public void set(java.lang.Object obj) {
if (obj instanceof test.RootType.Element2) {
setElement2(((test.RootType.Element2) obj));
} else {
if (obj instanceof test.RootType.Element1) {
setElement1(((test.RootType.Element1) obj));
} else {
throw new java.lang.IllegalArgumentException("Wrong argument class.");
}
}
}
/**
*
* @hibernate.many-to-one cascade="all" class="test.impl.RootTypeImpl$Element2Impl"
*
*/
public test.RootType.Element2 getElement2() {
return _Element2;
}
public void setElement2(test.RootType.Element2 theElement2) {
_Element2 = theElement2;
}
/**
*
* @hibernate.many-to-one cascade="all" class="test.impl.RootTypeImpl$Element1Impl"
*
*/
public test.RootType.Element1 getElement1() {
return _Element1;
}
public void setElement1(test.RootType.Element1 theElement1) {
_Element1 = theElement1;
}
/**
* @hibernate.id type="string" unsaved-value="null" length="32" generator-class="uuid.hex"
*
*/
public java.lang.String getIdInternal() {
return idInternal;
}
public void setIdInternal(java.lang.String anId) {
idInternal = anId;
}
}
Add an internal property (this property is already a homogeneous collection):
Code:
/**
*
* @hibernate.list cascade="all" where="Element1AndElement2Internal_index is not null"
* @hibernate.collection-key column="RootTypeImpl_id"
* @hibernate.collection-index column="Element1AndElement2Internal_index"
* @hibernate.collection-one-to-many class="test.impl.RootTypeImpl$Element1AndElement2Impl"
*
*/
public java.util.List getElement1AndElement2Internal() {
return _Element1AndElement2Internal;
}
public void setElement1AndElement2Internal(java.util.List theElement1AndElement2Internal) {
_Element1AndElement2Internal = theElement1AndElement2Internal;
}
The following class will heterogenize your homogeneous collection:
Code:
public class Element1AndElement2InternalProxyList
extends java.util.AbstractList
{
public java.lang.Object get(int index) {
test.RootType.Element1AndElement2 result = ((test.RootType.Element1AndElement2) _Element1AndElement2Internal.get(index));
return result.get();
}
public java.lang.Object set(int index, java.lang.Object o) {
test.RootType.Element1AndElement2 value = new test.impl.RootTypeImpl.Element1AndElement2Impl();
value.set(o);
test.RootType.Element1AndElement2 oldValue = ((test.RootType.Element1AndElement2) _Element1AndElement2Internal.set(index, value));
return oldValue.get();
}
public void add(int index, java.lang.Object o) {
test.RootType.Element1AndElement2 value = new test.impl.RootTypeImpl.Element1AndElement2Impl();
value.set(o);
_Element1AndElement2Internal.add(index, value);
}
public java.lang.Object remove(int index) {
test.RootType.Element1AndElement2 oldValue = ((test.RootType.Element1AndElement2) _Element1AndElement2Internal.remove(index));
return oldValue;
}
public int size() {
return _Element1AndElement2Internal.size();
}
}
Code:
protected List _Element1AndElement2 = new test.impl.RootTypeImpl.Element1AndElement2InternalProxyList();
private java.util.List _Element1AndElement2Internal = new java.util.ArrayList();
_Element1AndElement2 will contain elements of Element1 or Element2 types, while _Element1AndElement2Internal is a homogeneous collection containing only elements of type Element1AndElement2.