@OneToOne +每个具体类表 = 例外?
我是 Hibernate 新手,无法让 @OneToOne
在我们的代码中运行。
经过大量阅读后,我构建了一个孤立的示例,并想寻求社区的帮助。
假设有 3 个类:1 个抽象类 (Class_A) 和 2 个继承类 (Class_B / Class_C)。 Class_C 有一个指向 Class_B 的单向指针。
(我已经准备了一个图表,但该网站不允许我发布它:-/)。
备注:
- 纯Java + Hibernate 3.6.0 Final + Oracle 11g。
- 继承策略 = 每个具体类的表。
- 使用 hibernate.hbm2ddl.auto=update 开发。
- 在我们的代码中,Class_B 需要自己的表,因此没有
@Embeddable
。 - 在我们的代码中,Class_C 也是抽象的,不像这里的简化示例中所呈现的那样。
代码
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代码
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();
问题
在
<块引用>insert(classC)
Hibernate仅发出一条SQL来插入Class_C。没有插入 Class_B 的 SQL。我在 Oracle 中看到 Class_C 的详细信息,但 Class_B 的表是空的。
这是 SQL:Hibernate:插入 Class_C (classB_myId, myString, myId) 值 (?, ?, ?)
At
getTransaction().commit()
它会爆炸
:
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)
...
请提问
- 为什么这不起作用......我做错了什么?
- 在我们的遗留代码中,应用程序分配唯一的 ID 号,并且无意使用生成的 ID。因此,我们的
@Id
的@GenerateValue
不会被考虑。这是失败的原因吗? @OneToOne(cascade = CascadeType.ALL)
与@OneToOne
+@Cascade({CascadeType.ALL})
有什么区别?
非常感谢!
- 十种
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我猜原因是
尝试使用普通的
Session
来代替:StatelessSession
是一种特殊用途的工具,只应在特殊情况下使用。对于常规操作,您应该始终使用Session
。来自 Hibenrate 文档: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:请检查 Hibernate 文档。正如那里所说:
使用org.hibernate.StatelessSession,您可以处理对象之间的依赖关系插入对象时。当您使用 org.hibernate.Session 时,情况并非如此。
在这种情况下,您必须将 B 类对象保留在 C 类对象之前才能使其工作。坚持订单很重要。如果更改持久性顺序,将会出现org.hibernate.exception.ConstraintViolationException。仔细选择何时使用无状态会话,因为它没有持久性上下文。
使用 Hibernate 3.6.0 Final + MySQL 5.0.51a-24 进行测试
Please check Hibernate docs. As stated there:
With org.hibernate.StatelessSession, you have deal with object inter-dependencies when inserting objects. That's not the case when you are using a org.hibernate.Session.
In this case, you must persist classB object before classC object to make it work. Persisting order do counts. If you change the persistence order you will have org.hibernate.exception.ConstraintViolationException. Choose carefully when to use stateless sessions, as it has no persistence context.
Tested with Hibernate 3.6.0 Final + MySQL 5.0.51a-24