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