0

我面临一个实体(YieldCurveArchive)的持久记录问题,其字段(原因)的长度等于 2048 个字符。以下是场景及其结果:

  • 上传具有较小原因字段的新实体:工作正常。
  • 使用较大的(2048 个字符)数据集更改原因字段的上传实体:工作正常。再次如上。这是对现有记录的更新。
  • 上传具有较大(2048 个字符)原因字段的新实体:失败。

我也尝试使用 entityManager.flush() 刷新休眠查询缓冲区,但上述测试结果没有改变。

我怀疑 Hibernate 在实际执行最终插入数据库之前执行的缓冲可能存在问题:

  • 选择数据库中的可用记录以与现有数据集进行比较。
  • 插入被触发但只保存在休眠的缓冲区中以触发批量更新。
  • 为不同的客户触发了另一个选择。在看到另一个选择时,hibernate 决定将插入触发到数据库中,然后失败。

失败日志的跟踪摘录:

2013-07-02 12:46:00,792  WARN [pool-1-thread-4]: org.hibernate.util.JDBCExceptionReporter - SQL Error: 1400, SQLState: 23000
2013-07-02 12:46:00,792 ERROR [pool-1-thread-4]: org.hibernate.util.JDBCExceptionReporter - ORA-01400: cannot insert NULL into ("CORE_TOTEM"."YC_MONTHLY_ARCHIVE"."PKEY")

2013-07-02 12:46:00,792  WARN [pool-1-thread-4]: org.hibernate.util.JDBCExceptionReporter - SQL Error: 1400, SQLState: 23000
2013-07-02 12:46:00,792 ERROR [pool-1-thread-4]: org.hibernate.util.JDBCExceptionReporter - ORA-01400: cannot insert NULL into ("CORE_TOTEM"."YC_MONTHLY_ARCHIVE"."PKEY")

2013-07-02 12:46:00,985 ERROR [pool-1-thread-4]: org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
                        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
                        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:266)
                        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
                        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
                        at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64)
                        at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996)
                        at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1141)
                        at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
                        at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:65)
                        at markit.totem.dao.DaoHelper.list(DaoHelper.java:19)
                        at com.markit.totem.rates.yieldcurve.dao.YieldCurveArchiveDao.getArchivesMonthly(YieldCurveArchiveDao.java:172)
                        at com.markit.totem.rates.yieldcurve.dao.YieldCurveArchiveDao$$FastClassByCGLIB$$55ef1569.invoke(<generated>)
                        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
                        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:628)
                        at com.markit.totem.rates.yieldcurve.dao.YieldCurveMonthlyArchiveDao$$EnhancerByCGLIB$$6aa04fe7.getArchivesMonthly(<generated>)
                        at com.markit.totem.rates.yieldcurve.results.upload.monthly.YieldCurveMonthlyArchivePersister.getExisting(YieldCurveMonthlyArchivePersister.java:38)
                        at com.markit.totem.rates.yieldcurve.results.upload.YieldCurveArchivePersister.persist(YieldCurveArchivePersister.java:68)
                        at com.markit.totem.rates.yieldcurve.results.upload.YieldCurveArchivePersister$$FastClassByCGLIB$$ac0db3fb.invoke(<generated>)
                        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
                        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:628)
                        at com.markit.totem.rates.yieldcurve.results.upload.monthly.YieldCurveMonthlyArchivePersister$$EnhancerByCGLIB$$4b00cfa0.persist(<generated>)
                        at com.markit.totem.rates.yieldcurve.results.upload.YieldCurveResultsUploader.upload(YieldCurveResultsUploader.java:158)
                        at com.markit.totem.rates.yieldcurve.results.upload.YieldCurveResultsUploadTask.run(YieldCurveResultsUploadTask.java:53)
                        at com.markit.totem.workflow.WorkflowExecutor.executeWorkflowTask(WorkflowExecutor.java:258)
                        at com.markit.totem.workflow.WorkflowExecutor.executeSubWorkflow(WorkflowExecutor.java:227)
                        at com.markit.totem.workflow.WorkflowExecutor.access$000(WorkflowExecutor.java:17)
                        at com.markit.totem.workflow.WorkflowExecutor$1.run(WorkflowExecutor.java:72)
                        at markit.totem.dao.Transactionator.execute(Transactionator.java:19)
                        at markit.totem.dao.Transactionator$$FastClassByCGLIB$$c9204755.invoke(<generated>)
                        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
                        at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
                        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
                        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
                        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
                        at markit.totem.dao.Transactionator$$EnhancerByCGLIB$$4eec78e2.execute(<generated>)
                        at com.markit.totem.workflow.WorkflowExecutor.execute(WorkflowExecutor.java:83)
                        at com.markit.totem.workflow.WorkflowExecutor.execute(WorkflowExecutor.java:213)
                        at com.markit.totem.workflow.WorkflowManager$OldWorkflow.execute(WorkflowManager.java:218)
                        at com.markit.totem.workflow.WorkflowManager$1.run(WorkflowManager.java:119)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                        at java.lang.Thread.run(Thread.java:662)
Caused by: java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("CORE_TOTEM"."YC_MONTHLY_ARCHIVE"."PKEY")

                        at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:367)
                        at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9055)
                        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)

我最初的想法是,由于数据库中的编码差异和 Hibernate 的默认编码,它失败了。

像底层数据库使用 Oracle 和 NLS_CHARACTERSET 定义为:

NLS_CHARACTERSET    AL32UTF8

因此它将 1 个字符存储为 4 个字节,将任何特殊字符存储为 6 个字节。我插入 Oracle 失败了 1001,但通过了,直到我插入 1000 个字符。但是,如果我使用更多字符进行更新,情况并非如此,这会让人更加困惑。

任何指针都会有很大帮助吗?

4

0 回答 0