I have several entities which can have unique named properties. These are stored in a PROPERTY table with a composite-id of refType (which type of entity has the property), refId (The id of the entity instance which has the property) and the property name.
With two example entities FirstEntity and SecondEntity, I set properties using the following method:
Code:
public void addProperty(String name, String value) {
Property p = new Property(id.longValue(), refType, name); // refType is "FE" for FirstEntity and "SE" for SecondEntity
p.setValue(value);
properties.add(p);
}
Of course, this way I have to save the entity before I can set any properties, but that's not a problem. Now, I don't want to store the refType in the database for each entity, so I can't use a column for it. The problem differs from the manual section on "Components as composite identifiers" in that the ID of the entity is part of the composite key. The mapping I have will not work, as Hibernate generates foreign key constraints:
Code:
alter table PROPERTY add constraint FKF373CDD591B2E15FBE6 foreign key (ID) references SECOND_ENTITY
alter table PROPERTY add constraint FKF373CDD591B foreign key (ID) references FIRST_ENTITY
This will fail since the property table can contain ID values which occur only in FIRST_ENTITY or SECOND_ENTITY. I've tried to make the key on the set have multiple columns, but Hibernate then complains that the number of columns does not match the columns in the primary key on the entity tables.
I've searched through the forum as best I can, but despite looking at many composite-id examples I can't see one which is quite analogous to this. Can someone please help?
Hibernate version:2.1.7
Mapping documents:Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="com.rdc.model">
<class name="FirstEntity" table="FIRST_ENTITY" lazy="true">
<id name="id" type="long" column="ID" >
<generator class="native"/>
</id>
<property name="name" column="NAME" type="string" unique="true"/>
<set name="properties" cascade="all" lazy="true" where="type='FE'">
<key>
<column name="ID"/>
</key>
<one-to-many class="Property"/>
</set>
</class>
<class name="SecondEntity" table="SECOND_ENTITY" lazy="true">
<id name="id" type="long" column="ID" >
<generator class="native"/>
</id>
<property name="name" column="NAME" type="string" unique="true"/>
<set name="properties" cascade="all" lazy="true" where="type='SE'">
<key>
<column name="ID"/>
</key>
<one-to-many class="Property"/>
</set>
</class>
<class name="Property" table="PROPERTY">
<composite-id>
<key-property name="refType" column="TYPE"/>
<key-property name="refId" type="long" column="ID"/>
<key-property name="name" type="string" length="32" column="NAME" />
</composite-id>
<version name="version" column="VERSION" type="long" unsaved-value="undefined"/>
<property name="value" type="string" column="VALUE" not-null="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
Session session = factory.openSession();
Transaction t;
Set properties;
Long feid;
Long seid;
t = session.beginTransaction();
FirstEntity fe = new FirstEntity();
SecondEntity se = new SecondEntity();
fe.setName("first");
session.save(fe);
fe.addProperty("FEP1", "FEP1 Value");
fe.addProperty("FEP2", "FEP2 Value");
feid = fe.getId();
properties = fe.getProperties();
se.setName("second");
session.save(se);
se.addProperty("SEP1", "SEP1 Value");
se.addProperty("SEP2", "SEP2 Value");
seid = se.getId();
t.commit();
session.close();
Full stack trace of any exception that occurs:
net.sf.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at net.sf.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:73)
at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:30)
at net.sf.hibernate.impl.BatcherImpl.convert(BatcherImpl.java:325)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:134)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2441)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2391)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2260)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at com.rdc.model.test.HibernateTest.main(HibernateTest.java:56)
Caused by: java.sql.BatchUpdateException: ORA-02291: integrity constraint (S5USER.FKF373CDD591B2E15FBE6) violated - parent key not found
at oracle.jdbc.dbaccess.DBError.throwBatchUpdateException(DBError.java:459)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:3907)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:127)
... 5 more
Name and version of the database you are using:
Oracle 9.2.0.10
The generated SQL (show_sql=true):
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into FIRST_ENTITY (NAME, ID) values (?, ?)
Hibernate: insert into SECOND_ENTITY (NAME, ID) values (?, ?)
Hibernate: insert into PROPERTY (VERSION, VALUE, TYPE, ID, NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into PROPERTY (VERSION, VALUE, TYPE, ID, NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into PROPERTY (VERSION, VALUE, TYPE, ID, NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into PROPERTY (VERSION, VALUE, TYPE, ID, NAME) values (?, ?, ?, ?, ?)
Debug level Hibernate log excerpt:
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2291, SQLState: 23000
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02291: integrity constraint (S5USER.FKF373CDD591B2E15FBE6) violated - parent key not found
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2291, SQLState: 23000
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02291: integrity constraint (S5USER.FKF373CDD591B2E15FBE6) violated - parent key not found
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2291, SQLState: 23000
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02291: integrity constraint (S5USER.FKF373CDD591B2E15FBE6) violated - parent key not found
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
WARNING: SQL Error: 2291, SQLState: 23000
21-Jun-2005 14:07:16 net.sf.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ORA-02291: integrity constraint (S5USER.FKF373CDD591B2E15FBE6) violated - parent key not found
21-Jun-2005 14:07:16 net.sf.hibernate.impl.SessionImpl execute
SEVERE: Could not synchronize database state with session