记录Spring事务不生效的问题

首先要说明的一点是Spring的事务注解可以写在controller 也可以写在service层,下次见到写在controller层的事务注解不要惊讶....
注解失败的情况1

service层普通方法(testDeleteUser)调用带注解(deleteUserRunningTimeException)的方法,发生运行时异常后,回滚失败
解决办法:
普通方法(testDeleteUser)也加上注解
注:
如果在方法里进行了异常捕获,一定要抛出去,否则回滚依然不会生效

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

 /**
 * 普通方法调用注解方法
 */
//@Transactional
public void testDeleteUser(int id) {
   deleteUserRunningTimeException(id);
}
注解失败的情况2

service层方法报了非运行时异常,回滚操作失败
解决办法:
方法添加注解,声明为Exception类型进行回滚
@Transactional(rollbackFor = Exception.class),同样,如果捕获了异常,必须抛出去,否则回滚不会生效

/**
     * 测试非运行时异常,是否回滚
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserSimpleException(int id) throws Exception {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //创建要读取的数据文件的文件对象 file
            File file = new File("d:\\data.txt");
            //创建要读取数据的输入流
            fileReader = new FileReader(file);
            //从输入流中读取一个字符;
            int c = fileReader.read();
            //判断是否读取到文件结束,如果读取到文件的最后会返回-1
            while (c!=-1) {
                //输出读取的这个字符
                System.out.println((char)c);
                //再读取下一个字符
                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();
            }
        }
    }

    /**
     * 普通方法调用注解方法
     */
    @Transactional(rollbackFor = Exception.class)
    public void testDeleteUser(int id) throws Exception {
        deleteUserSimpleException(id);
    }
注解失败的情况2.1

实际项目中,并不会对每一个方法进行仔细的排查,再决定使用哪种注解,只需要捕获异常后抛出运行时异常就可以完成回滚操作
注:
这种方式注解就不需要指定某种类型的异常了,默认就是对运行时异常进行回滚

/**
     * 测试非运行时异常,是否回滚
     * @param id
     */
    @Transactional
    public void deleteUserSimpleException2(int id) {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //创建要读取的数据文件的文件对象 file
            File file = new File("d:\\data.txt");
            //创建要读取数据的输入流
            fileReader = new FileReader(file);
            //从输入流中读取一个字符;
            int c = fileReader.read();
            //判断是否读取到文件结束,如果读取到文件的最后会返回-1
            while (c!=-1) {
                //输出读取的这个字符
                System.out.println((char)c);
                //再读取下一个字符
                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();
            }
        }
    }

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

注解可以写在类声明上,也可以写在方法上,写在类声明上的时候表示调用该类的所有方法时都会启动事务,如果对个别方法有事务的个性化定制,则可以在方法上写注解,会按照就近原则执行注解

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

    /**
     * 测试非运行时异常,是否回滚
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserSimpleException(int id) throws Exception {

        FileReader fileReader = null;

        try {

            usersDao.deleteUserById(id);
            //创建要读取的数据文件的文件对象 file
            File file = new File("d:\\data.txt");
            //创建要读取数据的输入流
            fileReader = new FileReader(file);
            //从输入流中读取一个字符;
            int c = fileReader.read();
            //判断是否读取到文件结束,如果读取到文件的最后会返回-1
            while (c!=-1) {
                //输出读取的这个字符
                System.out.println((char)c);
                //再读取下一个字符
                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)

当注解中出现readOnly=true时,通常用于多表多表多表查询,数据库执行SQL时,会保证数据的一致性,查到的资料有说设置为true进行查询时,会提升性能,可能是我测试库数据量小的缘故,看不出区别
readOnly属性默认为false

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

你可能感兴趣的:(记录Spring事务不生效的问题)