2011-03-09 15 views
5

Niedawno zacząłem używać Spring Data Data Source Transaction Manager. Mam teraz problem. Moja transakcja obejmuje aktualizacje tabeli bazy danych i operację zapisu do pliku.Jak zarządzać transakcją (która obejmuje plik IO), gdy wyjątek IOException jest generowany z metody zamykania plików.

Działa dobrze, ale mam pewne wątpliwości dotyczące pliku I/O. Jak widać poniżej, skonfigurowałem metody openFile i closeFile mojego komponentu bean odpowiednio jako metodę init i metodę destroy, która z kolei zapewnia metody, które można nazwać tak jak constuructor i destruktor. Jeśli plik nie został poprawnie zamknięty, niektóre rekordy mogły nie zostać zapisane w pliku output.txt, co oznacza, że ​​nie byłem w stanie odpowiednio obsłużyć zarządzania transakcjami.

Chciałbym jednak przywrócić te aktualizacje DB, które nie zostały dołączone do płaskiego pliku. Dzięki mojemu rozwiązaniu nie można dodać metody fileClose do transakcji. Czy ktokolwiek wie, jak prawidłowo wdrożyć to pożądane działanie?

Wszelkie sugestie będą bardzo mile widziane

<!--XML CONFIGURATION --> 
<bean id="myFileWriter" class="com.job.step.ItemFileWriter" init-method="openFile" destroy-method="closeFile"> 
    <property name="jdbcTemplate" ref="jdbcTemplateProduct"/> 
</bean> 

public class ItemFileWriter implements ItemWriter<Item> { 
private static final Logger log = Logger.getLogger(ItemFileWriter.class); 
private BufferedWriter bw = null; 
public void openFile() throws IOException { 
    try { 
     bw = new BufferedWriter(new FileWriter("C:\\output.txt")); 
    } catch (IOException e) {   
     //log.error(e); 
     throw e; 
    }  
} 
public void closeFile() throws IOException { 
    if (bw != null) { 
     try { 
      bw.close(); 
     } catch (IOException e) { 
      log.error(e); 
      throw e; 
     } 
    } 
} 

@Transactional(rollbackFor = IOException.class) 
public void write(List<? extends Item> itemList) throws IOException 
{    
    for (Iterator<? extends Item> iterator = itemList.iterator(); iterator.hasNext();) { 
     Item item = (Item) iterator.next(); 

     String updateRtlnOutbound = "UPDATE SAMPLESCHEMA.SAMPLETABLE SET STATUS='TRANSFERRED' WHERE ID = ?"; 
     jdbcTemplate.update(updateRtlnOutbound, new Object[]{item.getID()}); 

     String item = String.format("%09d\n", item.customerNumber); 
     bw.write(item); 
    }       
} 
} 

Odpowiedz

3

Generalnie plik IO nie jest transakcyjny (z wyjątkiem niektórych funkcji specyficznych dla systemu operacyjnego).

Najlepiej więc, aby przenieść operację otwierania i zamykania do metody write(), aby wykonać je w ramach transakcji i wycofać transakcję, jeśli zamknięcie nie powiedzie się.

Należy jednak pamiętać, że nie można wycofać pliku IO w przypadku wycofania transakcji, więc w pewnych okolicznościach można uzyskać prawidłowy plik z elementami, podczas gdy w bazie danych elementy te nie są oznaczone jako TRANSFERRED.

Aby sove ten problem można spróbować użyć low-level transaction management support i spróbować usunąć plik w przypadku wycofania, ale myślę, że nadal nie może zapewnić silne gwarancje Konsystencja:

@Transactional(rollbackFor = IOException.class) 
public void write(List<? extends Item> itemList) throws IOException 
{     
    openFile(); 
    TransactionSynchronizationManager().registerSynchronization(new TransactionSynchronizationAdapter() { 
     public void afterCompletion(int status) { 
      if (status = STATUS_ROLLED_BACK) { 
       // try to delete the file 
      } 
     } 
    }); 

    try { 
     ... 
    } finally { 
     closeFile();       
    } 
} 
2

robisz operacje na dwóch różnych systemach: systemie plików i bazie danych. Zwykle transakcje XA ułatwiają nam łączenie różnych systemów transakcyjnych w jedną transakcję.

Większość baz danych można utworzyć w celu uczestniczenia w transakcjach XA. W systemie plików możesz użyć XADisk, aby włączyć XA. Po włączeniu XA w obu bazach danych (poprzez prawą konfigurację źródła danych) i systemie plików (przez Xadisk) można mieć pewność, że zarówno operacje na plikach i bazach danych są wykonywane, jak i obydwa z nich wycofane.

Powiązane problemy