【问题标题】:Hibernate session fails to query after ConstraintViolationException leading to AssertionFailure在 ConstraintViolationException 导致 AssertionFailure 之后,Hibernate 会话无法查询
【发布时间】:2013-08-08 14:49:02
【问题描述】:

我正在通过 Hibernate 对从文件到 MySQL 的记录进行批处理。我正在尝试遍历记录并保存它们,在 ConstraintViolationException 上我正在尝试更新 catch 子句中的记录。一些如何通过 AssertionFailure Exception 失败。

我一定会使用 Sessions 而不是 StatelessSessions。

try {
  System.out.println("Inserting "+key);
  session.save(mud);
} catch(HibernateException cve) {
    cve.printStackTrace();
    //log.error("Failed insert, record already exists: "+key);
    System.out.println("Failed insert, record already exists: "+key);
    List res = session.createQuery("from UserData as ud where ud.taskId = "+taskId+" and ud.userId= "+userId)
        .list();
    System.out.println("Query successfull");
    if (!res.isEmpty()) {
          mud.setId( ((UserData) res.get(0)).getId() );
          session.save(mud);
          continue;
}

}

这是 StackTrace:

Inserting 463531145008722
org.hibernate.exception.ConstraintViolationException: could not insert: [com.test.www.UserData]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2345)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2852)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at com.test.www.CSVToDB.LoadCSVToDB_statelessNoTransaction(CSVToDB.java:92)
at com.test.www.CSVToDB.run(CSVToDB.java:52)
at com.test.www.CSVToDB.main(CSVToDB.java:175)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '463531-145008722' for key 'taskId'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1041)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4190)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4122)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2818)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2157)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2460)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2377)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2361)
at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:94)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
... 18 more
Failed insert, record already exists: 463531145008722
org.hibernate.AssertionFailure: null id in com.test.www.UserData entry (don't flush the Session after an exception occurs)
at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:82)
at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at com.test.www.CSVToDB.LoadCSVToDB_statelessNoTransaction(CSVToDB.java:98)
at com.test.www.CSVToDB.run(CSVToDB.java:52)
at com.test.www.CSVToDB.main(CSVToDB.java:175)

【问题讨论】:

  • 您尝试先插入是否有特殊原因?如果你遵循(1)查询数据库寻找你想要的记录。 (2) 如果存在;然后节省泥浆...?
  • 是的,无论如何我都需要将记录保存到数据库中,如果记录已经存在,我需要进行更新。此外,由于要保存的记录的大小是巨大的(约 5000 万)查询,因此插入需要大量时间和数据库负载,更新也相对较少。

标签: mysql hibernate hibernateexception


【解决方案1】:

在 query.list() 期间看起来更好(并检查 Hibernate 代码)(在堆栈跟踪中查询成功丢失)和在查询执行之前运行自动刷新似乎是一个问题。尝试将 flushMode 更改为 COMMIT 或在查询之前执行 session.flush()。

你会为这种工作寻找 spring-batch 吗?

【讨论】:

  • from this Hibernate 将始终保存 mud,因为这是从其余代码创建的新对象。
  • 我不太明白:您正在创建带有newmud 项目,对吧? keymud 的 @Id 被保存了吗?在这种情况下,您可以执行mud.setId(key) 而不是执行mud = merge(mud)。你必须在 save() 一个瞬态对象之前重新附加对象(泥 @Id 是手动生成的还是 Hibernate 自动生成的)?
  • @Id 由 hibernate 自动生成。基本上我正在创建一个新对象,尝试将其插入数据库,如果由于记录已经在数据库中而插入失败(当前休眠会话可能会或可能不会创建),我正在检索记录并更新它与当前对象数据。
  • 最后一次尝试,我没有其他线索。在query.list()(在stacktrace 中Query successfull 缺失)和查询执行前自动刷新运行期间看起来更好(并检查Hibernate 代码)似乎是一个问题。尝试将 flushMode 更改为 COMMIT 或在查询之前执行 session.flush()。
  • 当我将刷新模式更改为 COMMIT 时它起作用了!谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 2021-09-20
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
相关资源
最近更新 更多