2012-08-22 124 views
1

我寫了一個使用java,jpa(和hibernate)的桌面應用程序。jpa「髒」交易

我有一個頁面,用戶可以編輯bean字段並將其保存到數據庫。 Bean的字段codice是唯一的。該數據庫有兩行,一行有codice = 0,第二行有codice = 00

該用法是編輯第一個豆0並將codice字段更改爲00,並嘗試將其保留。 entityManager.commit()將引發異常:

ERROR: Duplicate entry '00' for key 'codice'

捕捉到異常並向用戶顯示,它將codice字段修改爲11(尚不存在)並嘗試保留。

entityManager.commit()再次提高相同的異常

(ERROR: Duplicate entry '00' for key)

就像是試圖再次堅持老項目。

此情況下例如:

EntityManager em = Persistence.createEntityManagerFactory(
      "testNewDataModel").createEntityManager(); 
Articolo a = em.find(Articolo.class, 1L); 
EntityTransaction tx = em.getTransaction(); 
a.setNome("albi8"); 
// ---- 1 ---- just a normal commit, no errors 
tx.begin();  
a = em.merge(a);   
tx.commit();   
System.out.println("---- 1 ----"); 
// ---- 2 ---- will cause Duplicate entry error 
tx.begin();  
a.setCodice("00"); // already exist an item with codice = 00 -> Duplicate entry '00' for key 'codice' 
a = em.merge(a);   
try { 
    System.out.println("---- 2 ---- pre commit"); 
    tx.commit(); 
    System.out.println("---- 2 ---- after commit"); 
} catch (Exception e) { 
    System.out.println("Duplicate entry '00' for key 'codice'"); 
} 

// ---- 3 ---- trying to correct the previous error 

tx.begin(); 

a.setCodice("11"); //this code don't exist yet 
a.setNome("alby9"); 

a = em.merge(a); 

try { 
    System.out.println("---- 3 ---- pre commit"); 
tx.commit(); 
    System.out.println("---- 3 ---- after commit"); 
} catch (Exception e) { 
    e.printStackTrace(); //Duplicate entry '00' for key 'codice' 
} 

和她是輸出:

org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory 
22-ago-2012 18.41.02 org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init> 
INFO: HHH000397: Using ASTQueryTranslatorFactory 
Hibernate: select articolo0_._id as column1_12_0_, articolo0_.id_categoria as id10_12_0_, articolo0_.codice as codice12_0_, articolo0_.coefficiente_prezzo as coeffici3_12_0_, articolo0_.descrizione as descrizi4_12_0_, articolo0_.id_foto as id5_12_0_, articolo0_.nome as nome12_0_, articolo0_.posizione as posizione12_0_, articolo0_.prezzo_imponibile as prezzo8_12_0_, articolo0_.prezzo_vendita as prezzo9_12_0_, articolo0_1_.quantita as quantita13_0_ from inventario4.articolo articolo0_ left outer join inventario4.magazzino articolo0_1_ on articolo0_._id=articolo0_1_._id_articolo where articolo0_._id=? 
---- 1 ---- 
---- 2 ---- pre commit 
Hibernate: update inventario4.articolo set id_categoria=?, codice=?, coefficiente_prezzo=?, descrizione=?, id_foto=?, nome=?, posizione=?, prezzo_imponibile=?, prezzo_vendita=? where _id=? 
22-ago-2012 18.41.02 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
WARN: SQL Error: 1062, SQLState: 23000 
22-ago-2012 18.41.02 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
ERROR: Duplicate entry '00' for key 'codice' 
Duplicate entry '00' for key 'codice' 
---- 3 ---- pre commit 
Hibernate: update inventario4.articolo set id_categoria=?, codice=?, coefficiente_prezzo=?, descrizione=?, id_foto=?, nome=?, posizione=?, prezzo_imponibile=?, prezzo_vendita=? where _id=? 
22-ago-2012 18.41.02 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
WARN: SQL Error: 1062, SQLState: 23000 
22-ago-2012 18.41.02 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions 
ERROR: Duplicate entry '00' for key 'codice' 
javax.persistence.RollbackException: Error while committing the transaction 
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:90) 
    at org.lelmarir.test.Main.main(Main.java:79) 
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Duplicate entry '00' for key 'codice' 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289) 
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:78) 
    ... 1 more 
Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '00' for key 'codice' 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) 
    at $Proxy21.executeUpdate(Unknown Source) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3006) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237) 
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:272) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:264) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1081) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:315) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) 
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73) 
    ... 1 more 
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '00' for key 'codice' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) 
    at com.mysql.jdbc.Util.getInstance(Util.java:381) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3558) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3490) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2109) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2648) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2077) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2280) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2265) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) 
    ... 18 more 

最後一個問題:爲什麼交易仍然試圖堅持用codice = 00行?

+1

我錯過了什麼或真的沒有問號在你的問題? :) –

+0

好吧,我的錯,我認爲這是暗示:爲什麼交易仍然試圖堅持「codice」=「00」的行? – lelmarir

回答

0

我懷疑問題是您在事務之間重複使用相同的對象。我要麼clear實體經理,要麼使用find加載一個新對象。但我不確定,我很久沒有使用JPA了。

0

儘量明確地ROLLBACK TRANSACTION失敗後提交

try { 
System.out.println("---- 2 ---- pre commit"); 
tx.commit(); 
System.out.println("---- 2 ---- after commit"); 
} catch (Exception e) { 
    System.out.println("Duplicate entry '00' for key 'codice'"); 

    tx.rollback(); // HERE 

}