2012-04-10 26 views
5

Tôi đang cố gắng tạo giải pháp dựa trên Spring để chạy hàng loạt truy vấn SQL trên máy chủ MySQL 5.5. Bởi "truy vấn", tôi có nghĩa là bất kỳ câu lệnh SQL nào biên dịch, do đó, công việc hàng loạt SQL có thể chứa ví dụ một số câu lệnh CREATE TABLE, DELETE và INSERT.Spring TransactionManager - cam kết không hoạt động

Tôi đang sử dụng Spring Batch cho mục đích này.

Tôi có transactionManager được định cấu hình như sau.

<bean id="transactionManager" 
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 

dataSource:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="${batch.jdbc.driver}" /> 
    <property name="url" value="${batch.jdbc.url}" /> 
    <property name="username" value="${batch.jdbc.user}" /> 
    <property name="password" value="${batch.jdbc.password}" /> 
    <property name="maxIdle" value="10" /> 
    <property name="maxActive" value="100" /> 
    <property name="maxWait" value="10000" /> 
    <property name="validationQuery" value="select 1" /> 
    <property name="testOnBorrow" value="false" /> 
    <property name="testWhileIdle" value="true" /> 
    <property name="timeBetweenEvictionRunsMillis" value="1200000" /> 
    <property name="minEvictableIdleTimeMillis" value="1800000" /> 
    <property name="numTestsPerEvictionRun" value="5" /> 
    <property name="defaultAutoCommit" value="true" /> 
</bean> 

lớp DAO tôi có phương pháp cấu hình với

@Transactional(propagation = Propagation.REQUIRES_NEW) 

và tôi vòng qua một bộ sưu tập các câu lệnh SQL gọi phương thức với câu lệnh SQL đơn một thời gian. Việc xử lý bên trong phương pháp này là đơn giản như:

simpleJdbcTemplate.getJdbcOperations().execute(sql); 

Tôi mong rằng khi các phương pháp DAO hoàn tất, tôi sẽ xem kết quả trong DB. Tuy nhiên, nó có vẻ như chỉ khi thực hiện công việc mùa xuân hoàn thành các kết quả trở nên có sẵn trong DB.

Tôi cố gắng để thực hiện cam kết trong phương pháp DAO tôi:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
private void executeSingleQuery(String sql) { 
    PlatformTransactionManager transactionManager = (PlatformTransactionManager)context.getBean("transactionManager"); 


    DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 
    def.setPropagationBehavior(Propagation.REQUIRED.ordinal()); 

    TransactionStatus status = transactionManager.getTransaction(def); 

    try { 
     // execute your business logic here 
     log.info("about to execute SQL query[" + sql + "]"); 
     simpleJdbcTemplate.getJdbcOperations().execute(sql); 

    } catch (Exception e) { 
     log.info("SQL query was not committed due to exception and was marked for rollback"); 
     transactionManager.rollback(status); 
    } 

    transactionManager.commit(status); 

    if (transactionManager.getTransaction(null).isRollbackOnly() 
      && transactionManager.getTransaction(null).isCompleted()) { 
     log.info("SQL query commited!"); 
    } else { 
     log.info("SQL query was not committed due to: 1) the transaction has been marked for rollback " + 
       "2) the transaction has not completed for some reason"); 
    } 

    log.info("the query has completed"); 
} 

tôi sửa lỗi mã mùa xuân và thấy rằng các cam kết mà tôi gọi từ phương pháp DAO của tôi được thực hiện bởi TransactionTemplate (dòng chảy đạt dòng this.transactionManager.commit(status); và vượt qua mà không có ngoại lệ)

Tôi sẽ đánh giá cao bất kỳ lời khuyên nào nên được thực hiện để làm cho DAO phương pháp cam kết trên mỗi cuộc gọi (cam kết sau mỗi câu lệnh SQL nó thực hiện).

+0

Chú thích @Transactional sẽ xử lý cam kết. Trong mã của bạn, bạn không cần tham chiếu đến người quản lý giao dịch và cam kết thay đổi một cách rõ ràng, tôi giả sử. – ch4nd4n

Trả lời

8

Bạn không thể ủy quyền các phương pháp riêng tư. tức là @Transactional bạn có ở đây không có hiệu lực. Kéo phương thức này vào giao diện cha mẹ của bạn và nó sẽ hoạt động. Trừ khi bạn đã bật cài đặt proxyTargetClass không được khuyến nghị.

+0

thay đổi phương thức DAO thành công khai - cùng một vấn đề – aviad

+1

kéo phương thức lên giao diện cha mẹ đã giúp tình hình. Shukran!:) – aviad

3

Khi bạn gọi số executeSingleQuery() từ trong cùng một lớp, bạn sẽ không thông qua proxy để chú thích giao dịch sẽ không có hiệu lực.

Bạn đang trộn các giao dịch có khai báo và có lập trình, Có lẽ bạn muốn REQUIRES_NEW để bạn có thể xóa chú thích @Transactional vô nghĩa và sử dụng Propagation.REQUIRES_NEW khi thiết lập DefaultTransactionDefinition.

Ngoài ra, bạn có thể muốn di chuyển transactionManager.commit(status) bên trong khối try, mã hiện tại của bạn cuộn lại, sau đó thử thực hiện cam kết khi xảy ra Exception.

+0

Cảm ơn, tôi upvote câu trả lời của bạn bởi vì nó là hữu ích (một phần của nó). Tuy nhiên tôi không thể chấp nhận 2 câu trả lời - và MadheTo là người đầu tiên trả lời ... – aviad

0

Chúng tôi đã sử dụng chú thích @Rollback(value = false) và khắc phục sự cố bạn đang gặp phải.

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