true transaction example driven data annotation spring hibernate jpa transactions transactional

example - spring transaction propagation



Confirmar durante la transacción en @Transactional (4)

¿Es posible realizar la confirmación en el método que está marcado como Spring @Transactional ?

@PersistenceContext private EntityManager em; @Transactional(propagation = Propagation.REQUIRED) public void saveMembersWithMultipleCommits(List<Member> members) throws HibernateException { Iterator<Member> it = members.iterator(); while (it.hasNext()) { while (it.hasNext()) { Member wsBean = it.next(); em.persist(wsBean); // overall commit will be made after method exit log.info("Webservices record " + wsBean + " saved. " + i++); } } }

Me gustaría comprometerme con DB después de decir cada 500 elementos. ¿Es eso posible con el contexto antes mencionado?


No, debe hacerlo programáticamente utilizando, por ejemplo, la API de TransactionTemplate . Lea más aquí .

Se vería algo así como

while (it.hasNext()) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { int counter = 0; while (it.hasNext() && counter++ < 500) { Member wsBean = it.next(); em.persist(wsBean); log.info("Webservices record " + wsBean + " saved. " + i++); } } ); }


Si está esperando comprometerse transaccionalmente dentro de su otra transacción, es posible que necesite usar @Transactional (propagation = Propagation.REQUIRES_NEW)


Su pregunta sugiere que ha extraviado su límite de transacción.

Puede mover la llamada persistente a un método privado y hacer que ese método sea transaccional en lugar de externo. Este método podría aceptar 500 miembros a la vez y luego se comprometerá cuando salga.


La estrategia alternativa es crear un método en DAO y marcarlo como @Transactional. Este método hará una actualización masiva (por ejemplo, 500 nos). Entonces puedes tener un método con código

@Transactional public void mybatchUpdateMethod(){ StatelessSession session = this.hibernateTemplate.getSessionFactory() .openStatelessSession(); Transaction transaction = null; Long entryCounter = 0L; PreparedStatement batchUpdate = null; try { transaction = session.beginTransaction(); batchUpdate = session.connection().prepareStatement(insertSql); for (BatchSnapshotEntry entry : entries) { entry.addEntry(batchUpdate); batchUpdate.addBatch(); if (++entryCounter == 500) { // Reached limit for uncommitted entries, so commit batchUpdate.executeBatch(); } } batchUpdate.executeBatch(); batchUpdate.close(); batchUpdate = null; } catch (HibernateException ex) { transaction.rollback(); transaction = null; } }

Cada vez que llame a este método, se comprometerá después de 500 inserciones / actualizaciones