2012-08-22 6 views
1

J'ai écrit une application de bureau en utilisant java, jpa (et hibernate).jpa transaction "sale"

J'ai une page où un utilisateur peut éditer un champ de bean et l'enregistrer dans la base de données. Le champ codice du haricot est unique. La base de données a 2 rangées, une avec codice = 0 et la seconde avec codice = 00.

L'utilisation modifie le premier bean 0 et remplacez le champ codice par 00 et essayez de le conserver. entityManager.commit() lèvera une exception:

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

L'exception est interceptée et affichée à l'utilisateur, elle modifie le champ codice en 11 (ce qui n'existe pas encore) et tente de persister.

entityManager.commit() soulever à nouveau la même exception

(ERROR: Duplicate entry '00' for key)

comme si elle essayait encore de persister l'ancien article.

ici un exemple de cas:

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

et son est la sortie:

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 

et enfin la question: pourquoi la transaction essayer encore persister une ligne avec codice = 00?

+1

Ai-je raté quelque chose ou il n'y a vraiment pas de point d'interrogation dans votre question? :) –

+0

bien, ma faute, je pensais que c'était implicite: pourquoi la transaction essaie toujours de persister une rangée avec "codice" = "00"? – lelmarir

Répondre

0

Je suppose que le problème est que vous réutilisez le même objet entre les transactions. Je voudrais soit clear le gestionnaire d'entité, ou charger un nouvel objet en utilisant find. Mais je ne suis pas sûr, je n'utilise pas JPA depuis longtemps.

0

Essayez de rollback transaction après commettras a échoué explicitement

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 

} 
Questions connexes