2011-03-09 18 views
5

Gần đây tôi đã bắt đầu sử dụng Trình quản lý giao dịch nguồn dữ liệu của Spring. Tôi có một vấn đề bây giờ. Giao dịch của tôi bao gồm các cập nhật cho bảng DB và thao tác ghi vào một tệp.Cách quản lý giao dịch (bao gồm Tệp IO) khi một IOException được ném từ phương thức đóng tệp

Nó hoạt động tốt nhưng tôi có một số nghi ngờ về tệp I/O. Như bạn thấy dưới đây, tôi đã cấu hình các phương thức openFile và closeFile của bean của tôi như là phương thức init và phương thức hủy diệt, lần lượt cung cấp các phương thức đó được gọi giống như một constuructor và một destructor. Nếu tệp không được đóng đúng cách, một số bản ghi có thể không được ghi thành công vào tệp output.txt có nghĩa là tôi cũng không thể xử lý đúng cách quản lý giao dịch.

Tuy nhiên, tôi muốn khôi phục các cập nhật DB chưa được thêm vào tệp phẳng. Với giải pháp của tôi, có vẻ như không thể thêm phương thức fileClose vào giao dịch. Có ai biết cách thực hiện hành động mong muốn này đúng không?

Bất kỳ lời đề nghị sẽ được đánh giá rất

<!--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); 
    }       
} 
} 

Trả lời

3

Nói chung, file IO là không giao dịch (trừ một số tính năng hệ điều hành cụ thể). Vì vậy, tốt nhất bạn có thể làm là để di chuyển hoạt động mở và đóng sang phương thức write(), để thực hiện chúng bên trong một giao dịch và quay lại giao dịch nếu đóng không thành công. Quay lại đầu trang |||| Tuy nhiên, lưu ý rằng bạn không thể khôi phục tệp IO trong trường hợp quay lại giao dịch, do đó trong một số trường hợp, bạn có thể lấy đúng tệp với các mục, trong khi trong cơ sở dữ liệu các mục này không được đánh dấu là TRANSFERRED.

Để sove vấn đề này, bạn có thể thử sử dụng low-level transaction management support và cố gắng xóa các tập tin trong trường hợp của rollback, nhưng tôi nghĩ nó vẫn không thể cung cấp đảm bảo bền chặt:

@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

Bạn đang làm hoạt động trên hai hệ thống khác nhau: hệ thống tệp và cơ sở dữ liệu. Thông thường, các giao dịch XA giúp chúng ta dễ dàng kết hợp các hệ thống giao dịch khác nhau vào một giao dịch duy nhất.

Hầu hết các cơ sở dữ liệu có thể được thực hiện để tham gia vào các giao dịch XA. Đối với hệ thống tệp, bạn có thể sử dụng XADisk để bật XA. Khi bạn kích hoạt XA trên cả hai cơ sở dữ liệu (thông qua cấu hình đúng của nguồn dữ liệu) và hệ thống tệp (thông qua xadisk), bạn có thể chắc chắn rằng cả tệp và hoạt động của cơ sở dữ liệu cam kết hoặc cả hai đều khôi phục.

Các vấn đề liên quan