2013-08-07 2 views
0

하이버 네이트를 통해 파일 인에서 MySQL로 레코드의 배치 프로세싱을하고있다. 레코드를 반복하고 ConstraintViolationException에 저장하려고 해요. catch 절의 레코드를 업데이트하려고합니다. AssertionFailure Exception으로 어떻게 실패하는지Hibernate 세션이 AssertionFailure로 이어지는 ConstraintViolationException 이후에 쿼리하지 못한다.

StatelessSessions보다는 Sessions를 사용해야합니다. 쿼리 실행 전에 실행

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

(누락 된 스택 트레이스 쿼리 성공적인에서) query.list() 동안 문제가 보인다 나은 찾고 (및 최대 절전 모드 코드를 확인)과 자동 세척 : 여기

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; 
} 

} 

는 스택 트레이스의 . flushMode를 COMMIT으로 변경하거나 쿼리 전에 session.flush()를 수행하십시오.

이런 종류의 작업에 대해 스프링 배치를 보십니까?

+0

from [this] (http://stackoverflow.com/questions/6443672/hibernate-saveorupdate-behavior) Hibernate는 나머지 코드로부터 생성되는 새로운 객체이기 때문에 항상'mud'를 저장합니다. – Aryan

+0

나는 아주 잘 이해하지 못한다. 당신은'새'로'진흙'아이템을 만들고있다, 맞습니까? '열쇠'는'진흙'의 저장이되고 있습니까? 이 경우'mud = merge (mud)'를 수행하는 것보다'mud.setId (key)'를 할 수있다. Transient 오브젝트를 save()하기 전에 오브젝트를 재 부착해야한다. (진흙 @ 매뉴얼이나 Hibernate에 의해 자동 생성된다)? –

+0

@Id는 최대 절전 모드로 자동 생성됩니다. 기본적으로 나는 DB에 삽입하려고하는 새로운 개체를 만들고 있는데 레코드가 이미 데이터베이스 (현재의 최대 절전 모드 세션에 의해 생성 될 수도 있고 그렇지 않을 수도 있음) 때문에 삽입이 실패하면 레코드를 검색하고 업데이트 중이다. 현재 오브젝트 데이터를 가지고 있습니다. – Aryan