views:

105

answers:

4

Hi,

I have an entity that I want to persist through Hibernate (3.2) The EntityBean has a column that indicates how another value of the entity bean should be unmarshalled:

<class name="ServiceAttributeValue" table="service_attribute_value">
      <cache usage="nonstrict-read-write"/>
      <id name="id" column="id" type="int-long">
         <generator class="native"/>
      </id>
      <property name="serviceAttribute" type="service-attribute" column="service_attribute" not-null="true" />
      <!-- order is important here -->
      <property name="value" type="attribute-value" not-null="true">
         <column name="service_attribute" />
         <column name="id_value"/>
         <column name="enum_value"/>
         <column name="string_value"/>
         <column name="int_value"/>
         <column name="boolean_value"/>
         <column name="double_value"/>
      </property>
   </class>

The "service_attribute" column indicates which of the columns for the "value" property to look at when it unmarshalls the value and, more importantly, exactly what Type the value should be, for example the class of the Enum if the enum_value is to be read, or the type of Bean if the the id_value is to be read.

The value property uses a custom CompositeUserType to do the unmarshalling and within this I wish to reference the service_attribute column (although not write to it), however when I try to do this I get the following error:

org.hibernate.MappingException: Repeated column in mapping for entity: com.precurse.apps.rank.model.service.ServiceAttributeValue column: service_attribute (should be mapped with insert="false" update="false")

However within the definition of the composite property these xml attributes are not defined (only within a normal property).

Does anyone know of a way of overcoming this, or if there is a better solution to this propblem.

If you need any more information please let me know,

Cheers Simon

A: 

based on your description, it seems like what you want to do is creating different subclasses based on the service_attribute. Instead of trying to achieve repeated column mapping which is not allow in hibernate, you can take a look hibernate inheritance mapping.

Hi Hsiu, Thanks for replying to the post. What I'm trying to do is *avoid* having an inheritance hierarchy that you suggest. Each service *could*, in theory, be a subclass of the the main Service class, so I could have an Insurance service, Finance service, Gardening Service etc.Because their are so many possible services and because (in this domain at least) they are very simple name value type structures I'm trying to avoid having such a structure becausea. it would require programming overheadb. the behaviours of the services are really quite limited and are just data holders.
Simon B
A: 

I Think I found a solution albeit not a very elegant one.

in the

 public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
         throws HibernateException, SQLException {

method of the CompositeUserType the "owner" argument passed to the method contains the id of the object who's service_attribute I want to access.

Annoyingly the actual serviceAttribute of the owner is not accessable or has not been set at this stage (I played around with the ordering of the elements in the hbm.xml config, in case this was an ordering thing, but unfortunatly still no joy), so I can't simply access it.

Anyway the id of the owner object is set, so I then used the session argument to run a HQL query based on the id to access the serviceAttribute which I then used to correctly unmarshall the value property.

The drawback of this solution is that it requires a HQL query as an overhead to the unmarshalling process, although its within the same session, its still not optimal.

If anyone has any ideas for a better solution I'd be very grateful.

Cheers

Simon B
+1  A: 

I had a similar problem and changing the case of one column solved the problem. Could give a try!
e.g., one column could be service_attribute other Service_Attribute.

Padmarag
Ok, that's a good idea, I'll see if it works, thanks for the reply.
Simon B
+1  A: 

You can try this. Instead of mapping both values as property on the same table, map one of the property using join to itself and keep the other property as the way it is. This case you will be able to access the same property in both places. Just remember to name the property as different name.

      <join table="service_attribute_value">
         <key column = "id" />
         <property name="serviceAttribute" type="service-attribute" column="service_attribute" not-null="true"  />
      </join>

      <!-- order is important here -->
      <property name="value" type="attribute-value" not-null="true">
         <column name="service_attribute" />
         <column name="id_value"/>
         <column name="enum_value"/>
         <column name="string_value"/>
         <column name="int_value"/>
         <column name="boolean_value"/>
         <column name="double_value"/>
      </property>