【问题标题】:Using oracle auto increment trigger with hibernate在休眠中使用 oracle 自动增量触发器
【发布时间】:2012-04-17 09:21:08
【问题描述】:

我正在使用 hibernate 将我的 java 类映射到 oracle 表。对于我的主键 ID,我正在使用

<generator class="increment"></generator>

因为我的代码需要在两台机器上运行,所以经常遇到如下异常:

java.util.concurrent.ExecutionException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update

Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
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)
at jobsrc.BasicDaoImpl.save(BasicDaoImpl.java:65)

Caused by: java.sql.BatchUpdateException: ORA-00001: unique constraint (DB.SYS_C0011343) violated

at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10700)
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)
... 18 more

那是因为我使用的是休眠的增量,它会再次尝试内存中的最新数字。谁能展示我如何在休眠中使用oracle的auto_increment? 我直接在数据库中添加触发器,但是当它尝试调用 saveOrUpdate 时休眠崩溃:

org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
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)
at jobsrc.BasicDaoImpl.saveOrUpdate(BasicDaoImpl.java:37)

Caused by: java.sql.BatchUpdateException: No more data to read from socket
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10700)
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)
... 13 more

非常感谢!!!!!!!!!

【问题讨论】:

    标签: oracle hibernate hibernate-mapping database-trigger


    【解决方案1】:

    Oracle 没有 auto_increment 类型。您应该使用序列生成器,如this section of the Hibernate reference manual 中所示和解释。

    【讨论】:

    • 我的意思是直接在数据库中使用触发器
    • AFAIK,Hibernate 现在可以获取触发器生成的值。这是一个先有鸡还是先有蛋的问题:要获取生成的密钥,您需要生成的密钥。使用序列。
    • 您可能想查看该链接,您为锚标记添加了书签,但没有添加完整的网址。你能检查我编辑的网址是否正确吗?谢谢。
    • @Kev:是的。感谢您修复它。
    【解决方案2】:

    Hibernate 实际上可以读回触发器创建的值。实际上有两种方法可以做到这一点:

    1. 使用 org.hibernate.id.SequenceIdentityGenerator 生成器。这适用于 JDBC getGeneratedKeys 功能,特别是允许命名要返回的列的表单。这在数据库之间是高度不可移植的。而且,根据我的经验,它甚至无法跨 Oracle 驱动程序版本移植(尽管我已经很多年没有尝试过了)
    2. 使用 org.hibernate.id.SelectGenerator 生成器。这通过使用定义为唯一的属性的列从刚刚插入的行中选择标识符列来工作。您可以 (a) 配置生成器以告诉它唯一属性,或者 (b) 如果您碰巧使用 @NaturalId/ 映射,它会自动使用。

    但是,“插入后”标识符生成器(例如这两个以及 IDENTITY 生成器)通常会在您的应用程序的 impl 详细信息方面打开一个全新的蠕虫罐。我强烈建议不要使用“post insert”标识符生成器。 IMO,使用前面答案中讨论的序列生成器,你会好得多

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 2011-01-01
      • 2010-09-23
      相关资源
      最近更新 更多