記錄Spring事務(wù)不生效的問題

首先要說明的一點(diǎn)是Spring的事務(wù)注解可以寫在controller 也可以寫在service層,下次見到寫在controller層的事務(wù)注解不要驚訝....
注解失敗的情況1

service層普通方法(testDeleteUser)調(diào)用帶注解(deleteUserRunningTimeException)的方法,發(fā)生運(yùn)行時(shí)異常后,回滾失敗
解決辦法:
普通方法(testDeleteUser)也加上注解
注:
如果在方法里進(jìn)行了異常捕獲,一定要拋出去,否則回滾依然不會(huì)生效

@Transactional
public void deleteUserRunningTimeException(int id) {
    try {
          usersDao.deleteUserById(id);
            int num = 1 / 0;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

 /**
 * 普通方法調(diào)用注解方法
 */
//@Transactional
public void testDeleteUser(int id) {
   deleteUserRunningTimeException(id);
}
注解失敗的情況2

service層方法報(bào)了非運(yùn)行時(shí)異常,回滾操作失敗
解決辦法:
方法添加注解,聲明為Exception類型進(jìn)行回滾
@Transactional(rollbackFor = Exception.class),同樣,如果捕獲了異常,必須拋出去,否則回滾不會(huì)生效

/**
     * 測試非運(yùn)行時(shí)異常,是否回滾
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserSimpleException(int id) throws Exception {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //創(chuàng)建要讀取的數(shù)據(jù)文件的文件對(duì)象 file
            File file = new File("d:\\data.txt");
            //創(chuàng)建要讀取數(shù)據(jù)的輸入流
            fileReader = new FileReader(file);
            //從輸入流中讀取一個(gè)字符;
            int c = fileReader.read();
            //判斷是否讀取到文件結(jié)束,如果讀取到文件的最后會(huì)返回-1
            while (c!=-1) {
                //輸出讀取的這個(gè)字符
                System.out.println((char)c);
                //再讀取下一個(gè)字符
                c = fileReader.read();
            }

        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 普通方法調(diào)用注解方法
     */
    @Transactional(rollbackFor = Exception.class)
    public void testDeleteUser(int id) throws Exception {
        deleteUserSimpleException(id);
    }
注解失敗的情況2.1

實(shí)際項(xiàng)目中,并不會(huì)對(duì)每一個(gè)方法進(jìn)行仔細(xì)的排查,再?zèng)Q定使用哪種注解,只需要捕獲異常后拋出運(yùn)行時(shí)異常就可以完成回滾操作
注:
這種方式注解就不需要指定某種類型的異常了,默認(rèn)就是對(duì)運(yùn)行時(shí)異常進(jìn)行回滾

/**
     * 測試非運(yùn)行時(shí)異常,是否回滾
     * @param id
     */
    @Transactional
    public void deleteUserSimpleException2(int id) {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //創(chuàng)建要讀取的數(shù)據(jù)文件的文件對(duì)象 file
            File file = new File("d:\\data.txt");
            //創(chuàng)建要讀取數(shù)據(jù)的輸入流
            fileReader = new FileReader(file);
            //從輸入流中讀取一個(gè)字符;
            int c = fileReader.read();
            //判斷是否讀取到文件結(jié)束,如果讀取到文件的最后會(huì)返回-1
            while (c!=-1) {
                //輸出讀取的這個(gè)字符
                System.out.println((char)c);
                //再讀取下一個(gè)字符
                c = fileReader.read();
            }

        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            throw new RuntimeException(e.getCause());
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 普通方法調(diào)用注解方法
     */
    @Transactional
    public void testDeleteUser(int id) {
        deleteUserSimpleException2(id);
    }
注解的用法

注解可以寫在類聲明上,也可以寫在方法上,寫在類聲明上的時(shí)候表示調(diào)用該類的所有方法時(shí)都會(huì)啟動(dòng)事務(wù),如果對(duì)個(gè)別方法有事務(wù)的個(gè)性化定制,則可以在方法上寫注解,會(huì)按照就近原則執(zhí)行注解

@Service
@Transactional(readOnly = true)
public class UserServiceImpl {

    /**
     * 測試非運(yùn)行時(shí)異常,是否回滾
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserSimpleException(int id) throws Exception {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //創(chuàng)建要讀取的數(shù)據(jù)文件的文件對(duì)象 file
            File file = new File("d:\\data.txt");
            //創(chuàng)建要讀取數(shù)據(jù)的輸入流
            fileReader = new FileReader(file);
            //從輸入流中讀取一個(gè)字符;
            int c = fileReader.read();
            //判斷是否讀取到文件結(jié)束,如果讀取到文件的最后會(huì)返回-1
            while (c!=-1) {
                //輸出讀取的這個(gè)字符
                System.out.println((char)c);
                //再讀取下一個(gè)字符
                c = fileReader.read();
            }

        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        } finally {
            try {
                if (fileReader != null) {
                    fileReader.close();
                    fileReader = null;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
注解屬性(readOnly = true)

當(dāng)注解中出現(xiàn)readOnly=true時(shí),通常用于多表多表多表查詢,數(shù)據(jù)庫執(zhí)行SQL時(shí),會(huì)保證數(shù)據(jù)的一致性,查到的資料有說設(shè)置為true進(jìn)行查詢時(shí),會(huì)提升性能,可能是我測試庫數(shù)據(jù)量小的緣故,看不出區(qū)別
readOnly屬性默認(rèn)為false

https://www.cnblogs.com/milton/p/6046699.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容