2013-08-07 2 views
0

Я делаю пакетную обработку записей из файла в MySQL через Hibernate. Я пытаюсь перебрать записи и сохранить их, на ConstraintViolationException. Я пытаюсь обновить запись в catch. Некоторые о том, как это происходит с использованием исключения AssertionFailure.Сбой Hibernate не запрашивает после ConstraintViolationException, приводящего к AssertionFailure

У меня ограничено использование сессий, а не 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) 
+0

Есть ли у вас конкретная причина попробовать вставить первую? Как насчет того, если вы будете следовать (1) Запросите базу данных, которая ищет нужную запись. (2) Если существует; затем сохранить грязь ...? – Rafa

+0

да, мне нужно, чтобы запись была сохранена в базе данных в любом случае, только если запись уже существует, мне нужно будет сделать обновление. Кроме того, поскольку размер сохраняемых записей является огромным (~ 50 миллионов) запросов, тогда вставка занимает много времени и времени загрузки, а также обновления относительно редки. – Aryan

ответ

0

Глядя лучше (и проверка Hibernate коды) кажется проблема во время query.list() (в StackTrace запросов преуспевающего отсутствует) и автоматический поток запущен перед выполнением запроса , Попробуйте изменить flushMode для COMMIT или выполнить session.flush() перед запросом.

Вы смотрите на весеннюю партию для такого рода работ?

+0

из [this] (http://stackoverflow.com/questions/6443672/hibernate-saveorupdate-behavior) Hibernate всегда будет сохранять 'mud', потому что это новый объект, созданный из остальной части кода. – Aryan

+0

Я не очень хорошо понимаю: вы создаете элементы 'mud' с' new', правильно? Является ли 'ключ' @Id« грязи »? В этом случае вы можете сделать «mud.setId (ключ)», чем выполнить «mud = merge (mud)». Вы должны повторно привязать объект до сохранения() переходного объекта (Is mud @Id вручную или автоматически сгенерирован Hibernate)? –

+0

@Id автоматически генерируется спящим режимом. В основном я создаю новый объект, пытаясь вставить его в БД, и если вставка завершилась неудачей из-за того, что запись уже находится в базе данных (что может или не может быть создано текущим сеансом спящего режима), я беру запись и обновление он с данными текущего объекта. – Aryan

Смежные вопросы