更新不存在的表 - 崩溃 ORA-00942
我们在 Hibernate 尝试更新
一个不存在的表时遇到了奇怪的异常。以下是一个简单的示例(Hibernate 3.6.0 Final + Oracle 11g + Pure Java)。
这里 Class_A 是 TABLE_PER_CLASS 层次结构策略中的抽象(每个具体类一个表)。这是简单的版本,请告诉我我们的代码有什么问题:
Class_A
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Class_A {
@Id
@Column(name="blabla")
public long myId = 0;
}
Class_B
@Entity
public class Class_B extends Class_A {
private String myString = "Hellos - I'm Class_B!";
}
Class_C
@Entity
public class Class_C extends Class_A {
private String myString = "Hellos - I'm Class_C!";
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn
@OrderColumn(name="list_order")
public List<Class_A> as;
}
代码
Class_C c = new Class_C();
c.myId = 92;
Class_B b = new Class_B();
b.myId = 10;
List<Class_A> bs = new ArrayList<Class_A>();
bs.add(0, b);
c.as = bs;
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(c);
session.getTransaction().commit();
session.close();
崩溃
在 commit()
处,Hibernate 尝试以下 SQL:
Hibernate:更新 Class_A 设置为_blabla=?,list_order=? where blabla=?
然后崩溃:
java.sql.BatchUpdateException: ORA-00942: table or view does not exist
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.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
Hibernate 为什么这样做?
非常感谢!
- 十种
We've been getting a weird exception from Hibernate trying to update
a non-existent table. Following is a simple example (Hibernate 3.6.0 Final + Oracle 11g + Pure Java).
Here Class_A is abstract in a TABLE_PER_CLASS hierarchy strategy (table per concrete class). Here's the simple version, please tell me what's wrong with our code:
Class_A
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Class_A {
@Id
@Column(name="blabla")
public long myId = 0;
}
Class_B
@Entity
public class Class_B extends Class_A {
private String myString = "Hellos - I'm Class_B!";
}
Class_C
@Entity
public class Class_C extends Class_A {
private String myString = "Hellos - I'm Class_C!";
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn
@OrderColumn(name="list_order")
public List<Class_A> as;
}
Code
Class_C c = new Class_C();
c.myId = 92;
Class_B b = new Class_B();
b.myId = 10;
List<Class_A> bs = new ArrayList<Class_A>();
bs.add(0, b);
c.as = bs;
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(c);
session.getTransaction().commit();
session.close();
Crash
At commit()
, Hibernate tries this SQL:Hibernate: update Class_A set as_blabla=?, list_order=? where blabla=?
Then crashes on:
java.sql.BatchUpdateException: ORA-00942: table or view does not exist
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.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
Why does Hibernate do this?
Much thanks!
- Ten of a Kind
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您需要使关系成为双向的,并将一对多映射为多对一的逆关系。事实上,如果您查看 http ://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/inheritance.html#inheritance-limitations,您会注意到多态一对多仅限于 < code>inverse="true" 仅在每个具体类策略的表中。
因此,试试这个:
在 A 类中:
在 C 类中:
I think you need to make the relationships bidirectional, and map the one-to-many as the inverse relationship of the many-to-one. Indeed, if you look at http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/inheritance.html#inheritance-limitations, you'll note that polymorphic one-to-many is limited to
inverse="true"
only in the table per concrete-class strategy.Thus, try this :
In class A :
In class C :