|
First goes mappings, logs, code etc. Below find lyric description.
Mapping:
<class name="SimcCodedAddressTypeTest$SampleTestEntity2" table="address_entity2">
<id name="id" column="id" type="int">
<generator class="native"></generator>
</id>
<set name="sampleVOS" table="vos">
<key column="FKentity" not-null="true">
</key>
<composite-element
class="pl.frati.dynx.contact.hibernate.types.SimcCodedAddressTypeTest$SampleVO">
<property name="id" not-null="true" />
<property name="name" />
<property name="address"
type="pl.frati.dynx.contact.hibernate.types.SimcCodedAddressType">
<column name="simc_1" />
<column name="street_1" />
<column name="building_no_1" />
<column name="flat_no_1" />
<column name="postal_code_1" />
<column name="post_office_1" />
</property>
</composite-element>
</set>
</class>
Assume that there is entity that contains two value objects in the set, and the code tries to remove one of them:
session = sf.openSession();
session.beginTransaction();
entity = (SampleTestEntity2) session.get(SampleTestEntity2.class, entityId);
Assert.assertNotNull(entity);
Assert.assertNotNull(entity.sampleVOS);
Assert.assertEquals(2, entity.sampleVOS.size());
Assert.assertTrue(entity.sampleVOS.contains(vo1));
Assert.assertTrue(entity.sampleVOS.contains(vo2));
entity.sampleVOS.remove(vo2);
session.getTransaction().commit();
session.close();
This will cause an exception that is attached, but most important part is:
org.hibernate.exception.GenericJDBCException: could not delete collection rows: pl.frati.dynx.contact.hibernate.types.SimcCodedAddressTypeTest$SampleTestEntity2.sampleVOS#1 at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) Caused by: java.sql.SQLException: Invalid argument in JDBC call: parameter index out of range: 3 at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) [...] at pl.frati.dynx.contact.hibernate.types.SimcCodedAddressType.nullSafeSet(SimcCodedAddressType.java:195) [...] Caused by: org.hsqldb.HsqlException: Invalid argument in JDBC call: parameter index out of range: 3 at org.hsqldb.error.Error.error(Unknown Source)
and the log is:
Hibernate: delete from vos where FKentity=? and id=? 2014-02-18 17:46:11,536 INFO - HHH000010: On release of batch it still contained JDBC statements [[org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl]] 2014-02-18 17:46:11,537 WARN - SQL Error: -423, SQLState: S1000 [[org.hibernate.engine.jdbc.spi.SqlExceptionHelper]] 2014-02-18 17:46:11,537 ERROR - Invalid argument in JDBC call: parameter index out of range: 3 [[org.hibernate.engine.jdbc.spi.SqlExceptionHelper]]
What happens? Well it seems that there is some kind of bug in handling CompositeUserType. Hibernate tries to delete given Value Object. Normally, if there are no not-null properties in the composite-element everything goes fine - Hibernate runs following query:
delete from vos where FKentity=? and id=? and name=? and simc_1=? and street_1=? and building_no_1=? and flat_no_1=? and postal_code_1=? and post_office_1=?
However when any field is marked as not-null this causes creation of primary key. Lets assume that field id in composite-element is marked not-null. This should result in following SQL:
delete from vos where FKentity=? and id=?
And it does. The problem is that Hibernate still tries to bind values of address property, despite it does not belong to primary key. As they are not expected (only FKentity and id are expected) this causes index out of range exception, as there is no third parameter, so there is no parameter to bind to.
Workaround: Mark all properties in composite-element as not-null="false".
Other facts: 1. when no CompositeUserType is used everything works fine 2. when UserType is used everything works fine as well 3. CompositeUserType used in entity works fine
|