Spring Propagation.REQUIRES_NEW @ Подтверждение транзакции появляется в журнале только после завершения внешней транзакции. - PullRequest
0 голосов
/ 23 января 2012

У меня есть транзакционные методы, вызывающие друг друга, но кажется, что транзакция фиксируется после того места, где она должна быть зафиксирована, или после этого появляются по крайней мере журналы вставки. Вот иероглиф вызова:

@Override
@Transactional
public DataProcessingStatistics copyInitialRevision() {
    try {
        DataProcessingStatistics statistics = new DataProcessingStatistics();
        transaction(statistics);
        statistics.printResult();
        return statistics;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)  
public void transaction(DataProcessingStatistics statistics) {
    entityAuditTableService.generateTables(statistics);
    oneToManyRelationAuditTableService.generateTables(statistics);
    manyToManyRelationAuditTableService.generateTables(statistics);
}

...

 @Service
 public class EntityAuditTableServiceImpl implements EntityAuditTableService {
...

@Override
public void generateTables(DataProcessingStatistics statistics) {
    List<EntityAuditTable> auditTables = loadAll();
    for (EntityAuditTable auditTable : auditTables) {
        try {
            statistics.addAsProcessed(auditTable, process(auditTable));
        } catch (Exception e) {
            statistics.addAsSkipped(auditTable.getAuditTable(), e);             
        }
    }
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public int process(EntityAuditTable auditTable) {
    EntityDataTable table = entityDataTableService.create(auditTable.getEntityDataTable().getEntityClass());
    List<EntityDataTableRow> rows = entityDataTableService.readAllData(table);
    List<EntityAuditTableRow> auditTableRows = entityAuditTableRowService.generateTableData(auditTable, rows);
    entityAuditTableRowService.saveAll(auditTableRows);
    return auditTableRows.size();
}

...


 @Service
 public class EntityAuditTableRowServiceImpl implements EntityAuditTableRowService {

...


@Override
@Transactional
public void saveAll(List<EntityAuditTableRow> auditTableRows) {
    jdbcService.saveArraysAs500RowChunks(auditTableRows, new ListSaver<EntityAuditTableRow>(){
        @Override
        public void save(List<EntityAuditTableRow> list) {
            EntityAuditTableRowServiceImpl.this.saveJdbc(list);
            for (EntityAuditTableRow auditTableRow: list) {
                entityChangeService.saveFromRow(auditTableRow);
            }
        }
    });
}

...


@Service
public class JdbcServiceImpl implements JdbcService {

@Override
public <E> void saveArraysAs500RowChunks(List<E> rows, ListSaver<E> saver) {
    for (int i = 0; i < rows.size(); i += 500) {
        save500(rows.subList(i, Math.min(i +500, rows.size())), saver);
    }
}

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public <E> void save500(final List<E> rows, ListSaver<E> saver) {
    if (rows == null || rows.size() == 0) {
        return;
    }
    if (rows.size() > 500) {
        throw new IllegalStateException("(auditTableRows.size() > 500)");
    }
    saver.save(rows);
}   

...

@Service
public class EntityChangeServiceImpl implements EntityChangeService {


@Override
@Transactional
public void saveFromRow(EntityAuditTableRow auditTableRow) {
    Revision revision = revisionsService.load(auditTableRow.getAuditTableRow().getRevision().getId());
    EntityChange entityChange = create(auditTableRow);
    save(entityChange);
    revision.getEntitiesChanges().add(entityChange);
    revisionsService.save(revision);
}

...
@Service
public class RevisionServiceImpl implements RevisionService {

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Revision create() {
    Revision revisionEntity = createDetached();
    long generateNextIdForClass = idService.generateNextIdForClass(Revision.class);
    revisionEntity.setId(generateNextIdForClass);
    revisionEntity.setTimestamp(new Date());
    save(revisionEntity);
    return revisionEntity;
}

@Override
@Transactional
public void save(Revision revisionEntity) {
    persistenceManagerHibernate.save(revisionEntity);
}

Дело только в том, что после возврата из корневого / начального вызова метода я получаю вставки в журналы для таблицы ENTITY_CHANGED_IN_REVISION / EntityChange:

этот пункт:

@Override
@Transactional
public DataProcessingStatistics copyInitialRevision() {
    try {
        DataProcessingStatistics statistics = new DataProcessingStatistics();
        transaction(statistics);
        statistics.printResult();
        return statistics; // only after that return insert log appear
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

этот журнал появляется только после возврата:

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Hibernate: insert into ENTITY_CHANGED_IN_REVISION (ENTITY_ID, ENTITY_NAME, GROUP_ENTITY_ID, GROUP_NAME, REV_ID, REVISION_TYPE, ID) values (?, ?, ?, ?, ?, ?, ?)

Вместо того, чтобы открывать их после возврата из метода «сохранить 500 строк», который является @Transactional (распространение = Propagation.REQUIRES_NEW):

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public <E> void save500(final List<E> rows, ListSaver<E> saver) {
    if (rows == null || rows.size() == 0) {
        return;
    }
    if (rows.size() > 500) {
        throw new IllegalStateException("(auditTableRows.size() > 500)");
    }
    saver.save(rows); // invokes EntityChangeServiceImpl.saveFromRow
}   

...

@Service
public class EntityChangeServiceImpl implements EntityChangeService {


@Override
@Transactional
public void saveFromRow(EntityAuditTableRow auditTableRow) {
    Revision revision = revisionsService.load(auditTableRow.getAuditTableRow().getRevision().getId());
    EntityChange entityChange = create(auditTableRow);
    save(entityChange);
    revision.getEntitiesChanges().add(entityChange);
    revisionsService.save(revision);
}

Ответы [ 2 ]

1 голос
/ 09 августа 2012

Транзакционный метод класса вызывает другой транзакционный метод этого класса без прокси, поэтому транзакция второго метода не используется при вызове.

0 голосов
/ 08 августа 2012

Чтобы применить @Transactional и, таким образом, открыть его, выполнение должно быть выполнено через proxy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...