0

我是 Hibernate 的新手,我无法@OneToOne在我们的代码中运行。
经过大量阅读,我构建了一个隔离示例,并想向社区寻求帮助。

假设 3 个类:1 个抽象(Class_A)和 2 个继承自它(Class_B / Class_C)。Class_C 有一个指向 Class_B 的单向指针。
(我已经准备了一个图表,但该网站不会让我发布它:-/)。

笔记:

  1. 纯 Java + Hibernate 3.6.0 Final + Oracle 11g。
  2. 继承策略 =每个具体类的表
  3. hibernate.hbm2ddl.auto=update.
  4. 在我们的代码中 Class_B 需要它自己的表,因此没有@Embeddable.
  5. 在我们的代码中 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;
    }
}

休眠代码

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();

问题

  1. insert(classC)Hibernate 只发出一条 SQL 来插入 Class_C。没有用于插入 Class_B 的 SQL。我在 Oracle 中看到 Class_C 的详细信息,但 Class_B 的表是空的。
    这是SQL:

    Hibernate:插入 Class_C (classB_myId, myString, myId) 值 (?, ?, ?)

  2. 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)
...

问题请

  1. 为什么这不起作用......我做错了什么?
  2. 在我们的遗留代码中,应用程序分配唯一的 id 编号并且无意使用生成的 Id。因此不考虑@GenerateValue我们的。@Id这是失败的原因吗?
  3. @OneToOne(cascade = CascadeType.ALL)vs. @OneToOne+和有什么不一样@Cascade({CascadeType.ALL})

非常感谢!

  • 十种
4

2 回答 2

0

我想原因是

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 

尝试使用普通的Session代替:

Session session = sessionFactory.openSession(); 

StatelessSession是一种特殊用途的工具,只能在特殊情况下使用。对于常规操作,您应该始终使用Session. 来自 Hibenrate 文档:

或者,Hibernate 提供了一个面向命令的 API,可用于将数据以分离对象的形式传入和传出数据库。StatelessSession 没有与之关联的持久性上下文,并且不提供许多更高级别的生命周期语义。特别是,无状态会话不实现一级缓存,也不与任何二级缓存或查询缓存交互。它不实现事务性后写或自动脏检查。使用无状态会话执行的操作永远不会级联到关联的实例。

于 2011-02-15T16:01:16.413 回答
0

请检查休眠文档。如那里所述:

使用无状态会话执行的操作永远不会级联到关联的实例。 http://docs.jboss.org/hibernate/core/3.3/reference/en-US/html/batch.html#batch-statelesssession

使用org.hibernate.StatelessSession,您可以在插入对象时处理对象之间的依赖关系。当您使用org.hibernate.Session时,情况并非如此。

在这种情况下,您必须在 classC 对象之前持久化classB 对象以使其工作。坚持订单确实很重要。如果您更改持久性顺序,您将拥有org.hibernate.exception.ConstraintViolationException。谨慎选择何时使用无状态会话,因为它没有持久性上下文。

statelessSession.beginTransaction();

statelessSession.insert(classB); // <- Persisting classB

statelessSession.insert(classC);
statelessSession.getTransaction().commit();
statelessSession.close();

使用 Hibernate 3.6.0 Final + MySQL 5.0.51a-24 测试

于 2011-02-15T17:26:07.513 回答