2012-01-23 3 views
0

트랜잭션 메소드가 서로 호출되지만 커밋해야하는 트랜잭션이 커밋되거나 적어도 삽입 로그가 커밋 된 것처럼 보입니다. 여기에 통화 hierachy은 다음과 같습니다Spring Propagation.REQUIRES_NEW @ 트랜잭션 트랜잭션 종료 후 로그에 트랜잭션 커밋이 나타납니다.

@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 행 덩어리를 저장"방법에서 복귀 한 후이를 reveiving의 @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); 
} 

답변

0

@Transactional을 적용하고 따라서를 열려면, 실행은 proxy 통해 수행해야합니다 .

1

클래스의 트랜잭션 메소드는 프록시없이이 클래스의 다른 트랜잭션 메소드를 호출하므로, 두 번째 메소드 트랜잭션은 호출에 사용되지 않습니다.