@Transactional 錯誤使用的幾種場景


@RestController
public class AController {

    @Autowired
    AService aService;

    // 回滾
    @GetMapping("direct")
    public void direct() {
        aService.testTransactional();
    }

    // 不回滾
    @GetMapping("indirect")
    public void indirect() {
        aService.testTransactionalIndirect();
    }

    // 不回滾
    @GetMapping("nonPublic")
    public void nonPublic() {
        aService.testTransactionalNonPublic();
    }

    // 不回滾
    @GetMapping("catchException")
    public void catchException() {
        aService.testTransactionalCatchException();
    }

    // 不回滾
    @GetMapping("sqlException")
    public void sqlException() throws SQLException {
        aService.testTransactionalSQLException();
    }

    // 回滾
    @GetMapping("sqlExceptionWithRollbackfor")
    public void sqlExceptionWithRollbackfor() throws SQLException {
        aService.testTransactionalSQLExceptionWithRollbackfor();
    }
}

 

@Service
public class AService {

    @Autowired
    TestTableDAO testTableDAO;

    // 回滾
    @Transactional
    public void testTransactional() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);

        throw new RuntimeException("exception");
    }

    // 不回滾: 類內部方法調用本類內部的其他方法並不會引起事務行爲,即使被調用方法使用@Transactional註解進行修飾
    public void testTransactionalIndirect() {
        testTransactional();
    }

    // 不回滾: @Transaction註解只對方法名爲pubic的才生效
    @Transactional
    void testTransactionalNonPublic() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);

        throw new RuntimeException("exception");
    }

    // 不回滾
    @Transactional
    public void testTransactionalCatchException() {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);

        try {
            throw new RuntimeException("exception");
        } catch (Exception e) {
            System.out.println("catch");
        }
    }

    // 不回滾: @Transactional默認情況下只回滾RuntimeException和Error
    @Transactional
    public void testTransactionalSQLException() throws SQLException {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);

        throw new SQLException("exception");
    }

    // 回滾: 指定在 SQLException 異常發生時回滾
    @Transactional(rollbackFor = {
            SQLException.class
    })
    public void testTransactionalSQLExceptionWithRollbackfor() throws SQLException {
        ATestTable er = new ATestTable();
        er.setSummary("test");
        testTableDAO.save(er);

        throw new SQLException("exception");
    }
}

 

@Repository
public interface TestTableDAO
        extends JpaRepository<ATestTable, Integer>, JpaSpecificationExecutor<ATestTable> {

}

 

@Entity
@Data
@Table(name = "test")
public class ATestTable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    int id;

    @Column(name = "summary", length = 512)
    String summary;
}

 

 

 

發佈了208 篇原創文章 · 獲贊 32 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章