首先,请参阅Hibernate映射摘录:Oracle DB中的可变父对象在Oracle DB VIEW中引用不可变的ChildObject:
1)在ParentObject中有一组ChildObjectInView,定义为不可变,没有级联:
<class name="ParentObject" table="t_parentobject">
...
<set name="childObjectsInView" cascade="none" lazy="true" mutable="false">
<key column="coivId" />
<one-to-many class="com.it.ChildObjectInView"/>
</set>
</class>
2)ChildObjectInView被定义为
<class name="ChildObjectInView" table="view_coiv" mutable="false" lazy="true">
...
<many-to-one name="parentObject" column="parentObjectId" update="false" insert="false" class="com.it.ParentObject" not-null="true" outer-join="true">
</many-to-one>
</class>
调用com.it.TestServiceImpl。 saveParentObject()会导致Oracle错误 ORA-01732:数据操作操作在此视图上不合法,尽管在该视图中有mutable =“false”属性已设置hibernate映射。为什么会出现这个错误?
com.it.TestBean|could not delete collection: [com.it.ParentObject.childObjectsInView#398500]
org.hibernate.exception.SQLGrammarException: could not delete collection: [com.it.ParentObject.childObjectsInView#398500]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:67)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.collection.AbstractCollectionPersister.remove(AbstractCollectionPersister.java:1071)
at org.hibernate.action.CollectionRemoveAction.execute(CollectionRemoveAction.java:28)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at com.it.TestServiceImpl.saveParentObject(TestServiceImpl.java:418)
Caused by: java.sql.BatchUpdateException: ORA-01732: data manipulation operation not legal on this view
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10296)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:216)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.java:34)
at org.hibernate.persister.collection.AbstractCollectionPersister.remove(AbstractCollectionPersister.java:1048)
... 69 more
答案 0 :(得分:0)
我终于发现,有些情况是ParentObject
是新设置的,ParentObject.childObjectsInView
集设置为null
。
保存这个新创建的ParentObject
Hibernate尝试运行DELETE FROM <view> WHERE id=<objectid>
。此语句类似于ParentObject.childObjectsInView
内的所有对象的重置。
我认为Hibernate的默认行为在这个地方是错误的,应该打开一个错误报告:Hibernate知道子进程是不可变的,所以任何操作SQL都应该被抑制。
解决方法:强>
确保空集合始终设置为ParentObject.childObjectsInView
(而不是null
)。