I'm new to Hibernate, and I can't get @OneToOne
to function in our code.
After much reading, I've constructed an isolates example, and thought to ask the help of the community.
Suppose 3 classes: 1 abstract (Class_A) and 2 inheriting from it (Class_B / Class_C). Class_C has a unidirectional pointer to Class_B.
(I've prepared a diagram but the site wont let me post it :-/).
Notes:
- Pure Java + Hibernate 3.6.0 Final + Oracle 11g.
- Inheritance strategy = Table per Concrete Class.
- Developed with
hibernate.hbm2ddl.auto=update
. - In our code Class_B needs its own table, thus no
@Embeddable
. - In our code Class_C is also abstract, not as presented here in the simplified example.
Code
Class_A
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Class_A {
@Id
public long myId = 0;
}
Class_B
@Entity
@Table(name = "Class_B")
public class Class_B extends Class_A {
private String myString = "Hellos - I'm Class_B!";
}
Class_C
@Entity
@Table(name = "Class_C")
public class Class_C extends Class_A {
private String myString = "Hellos - I'm Class_C!";
@OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@NotNull
private Class_B classB;
public void setClassB(Class_B classB) {
this.classB = classB;
}
}
Hibernate Code
StatelessSession statelessSession = sessionFactory.openStatelessSession();
Class_C classC = new Class_C();
classC.myId = 92;
Class_B classB = new Class_B();
classB.myId = 8000;
classC.setClassB(classB);
statelessSession.beginTransaction();
statelessSession.insert(classC);
statelessSession.getTransaction().commit();
statelessSession.close();
Problems
At
insert(classC)
Hibernate only issues an SQL to insert Class_C. There is no SQL to insert Class_B. I see Class_C's details in Oracle, but Class_B's table is empty.
Here's the SQL:Hibernate: insert into Class_C (classB_myId, myString, myId) values (?, ?, ?)
At
getTransaction().commit()
it explodes with
this:
java.sql.BatchUpdateException: ORA-02291: integrity constraint (NDP.FK9619CF1CAD47EF0F) violated - parent key not found
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:17660)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:771)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.impl.StatelessSessionImpl.managedFlush(StatelessSessionImpl.java:333)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
...
Questions Please
- Why doesn't this work... what am I doing wrong?
- In our legacy code, the application allocates unique id numbers and have no intention of using generated Ids. Thus
@GenerateValue
for our@Id
isn't considered. Is this a reason why this fails? - Whats the difference between
@OneToOne(cascade = CascadeType.ALL)
vs.@OneToOne
+@Cascade({CascadeType.ALL})
?
MUCH thanks!
- Ten_of_a_Kind
I guess the cause is
Try to use a normal
Session
instead:StatelessSession
is a special purpose tool that should be used only in special circumstances. For regular operations you should always useSession
. From Hibenrate docs: