• 吴裕雄天生自然SPRING基于@Transactional注解的声明式事务管理


     @Transactional注解可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有public方法将都具有该类型的事务属性,同时,也可以在方法级别使用该注解来覆盖类级别的定义。虽然@Transactional注解可以作用于接口、接口方法、类以及类方法上,但是Spring小组建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。
    如何在事务处理中捕获异常
    
    声明式事务处理的流程是:1)Spring根据配置完成事务定义,设置事务属性。2)执行开发者的代码逻辑。3)如果开发者的代码产生异常(如主键重复)并且满足事务回滚的配置条件,则事务回滚;否则,事务提交。4)事务资源释放。
        现在的问题是,如果开发者在代码逻辑中加入了try...catch...语句,Spring还能不能在声明式事务处理中正常得到事务回滚的异常信息?答案是不能。
    1)修改@Transactional注解
    我们需要将TestServiceImpl类中的@Transactional注解修改为:
    @Transactional(rollbackFor= {Exception.class})
    //rollbackFor指定回滚生效的异常类,多个异常类逗号分隔;
    //noRollbackFor指定回滚失效的异常类
    2)在catch语句中添加“throw new RuntimeException();”语句。
    注意:在实际工程应用中,经常在catch语句中添加“TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();”语句即可。也就是说,不需要在@Transaction注解中添加rollbackFor属性。
    package entity;
    
    public class MyUser {
        private Integer uid;
        private String uname;
        private String usex;
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public String getUname() {
            return uname;
        }
    
        public void setUname(String uname) {
            this.uname = uname;
        }
    
        public String getUsex() {
            return usex;
        }
    
        public void setUsex(String usex) {
            this.usex = usex;
        }
    
        public String toString() {
            return "myUser [uid=" + uid + ", uname=" + uname + ", usex=" + usex + "]";
        }
    }
    package service;
    
    public interface TestService {
        public void testJDBC();
    }
    package service;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.transaction.interceptor.TransactionAspectSupport;
    
    import dao.TestDao;
    import entity.MyUser;
    
    @Service
    @Transactional   //@Transactional(rollbackFor= {Exception.class})
    public class TestServiceImpl implements TestService {
        @Autowired
        public TestDao testDao;
    
        @Override
        public void testJDBC() {
            String insertSql = "insert into user values(null,?,?)";
            // 数组param的值与insertSql语句中?一一对应
            Object param1[] = { "chenheng1", "男" };
            Object param2[] = { "chenheng2", "女" };
            Object param3[] = { "chenheng3", "男" };
            Object param4[] = { "chenheng4", "女" };
            String insertSql1 = "insert into user values(?,?,?)";
            Object param5[] = { 1, "chenheng5", "女" };
            Object param6[] = { 1, "chenheng6", "女" };
            try {
                // 添加用户
                testDao.update(insertSql, param1);
                testDao.update(insertSql, param2);
                testDao.update(insertSql, param3);
                testDao.update(insertSql, param4);
                // 添加两个ID相同的用户,出现唯一性约束异常,使事物回滚。
                testDao.update(insertSql1, param5);
                testDao.update(insertSql1, param6);
                // 查询用户
                String selectSql = "select * from user";
                List<MyUser> list = testDao.query(selectSql, null);
                for (MyUser mu : list) {
                    System.out.println(mu);
                }
            } catch(Exception e) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                System.out.println("主键重复,事务回滚。");
                throw new RuntimeException();
            }
        }
    }
    package dao;
    
    import java.util.List;
    import entity.MyUser;
    
    public interface TestDao {
        public int update(String sql, Object[] param);
    
        public List<MyUser> query(String sql, Object[] param);
    }
    package dao;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.BeanPropertyRowMapper;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.RowMapper;
    import org.springframework.stereotype.Repository;
    
    import entity.MyUser;
    
    @Repository
    public class TestDaoImpl implements TestDao {
        @Autowired
        // 使用配置类中的JDBC模板
        private JdbcTemplate jdbcTemplate;
    
        /**
         * 更新方法,包括添加、修改、删除 param为sql中的参数,如通配符?
         */
        @Override
        public int update(String sql, Object[] param) {
            return jdbcTemplate.update(sql, param);
        }
    
        /**
         * 查询方法 param为sql中的参数,如通配符?
         */
        @Override
        public List<MyUser> query(String sql, Object[] param) {
            RowMapper<MyUser> rowMapper = new BeanPropertyRowMapper<MyUser>(MyUser.class);
            return jdbcTemplate.query(sql, rowMapper);
        }
    }
    package config;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @Configuration // 通过该注解来表明该类是一个Spring的配置,相当于一个xml文件
    @ComponentScan(basePackages = { "dao", "service" }) // 配置扫描包
    @PropertySource(value = { "classpath:jdbc.properties" }, ignoreResourceNotFound = true)
    //配置多个配置文件  value={"classpath:jdbc.properties","xx","xxx"}
    @EnableTransactionManagement // 开启声明式事务的支持
    public class SpringJDBCConfig {
        @Value("${jdbc.url}") // 注入属性文件jdbc.properties中的jdbc.url
        private String jdbcUrl;
        @Value("${jdbc.driverClassName}")
        private String jdbcDriverClassName;
        @Value("${jdbc.username}")
        private String jdbcUsername;
        @Value("${jdbc.password}")
        private String jdbcPassword;
    
        /**
         * 配置数据源
         */
        @Bean
        public DriverManagerDataSource dataSource() {
            DriverManagerDataSource myDataSource = new DriverManagerDataSource();
            // 数据库驱动
            myDataSource.setDriverClassName(jdbcDriverClassName);
            ;
            // 相应驱动的jdbcUrl
            myDataSource.setUrl(jdbcUrl);
            // 数据库的用户名
            myDataSource.setUsername(jdbcUsername);
            // 数据库的密码
            myDataSource.setPassword(jdbcPassword);
            return myDataSource;
        }
    
        /**
         * 配置JdbcTemplate
         */
        @Bean(value = "jdbcTemplate")
        public JdbcTemplate getJdbcTemplate() {
            return new JdbcTemplate(dataSource());
        }
    
        /**
         * 为数据源添加事务管理器
         */
        @Bean
        public DataSourceTransactionManager transactionManager() {
            DataSourceTransactionManager dt = new DataSourceTransactionManager();
            dt.setDataSource(dataSource());
            return dt;
        }
    }
    package config;
    
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import service.TestService;
    
    public class TestJDBC {
        public static void main(String[] args) {
            // 初始化Spring容器ApplicationContext
            AnnotationConfigApplicationContext appCon = new AnnotationConfigApplicationContext(SpringJDBCConfig.class);
            TestService ts = appCon.getBean(TestService.class);
            ts.testJDBC();
            appCon.close();
        }
    }

  • 相关阅读:
    WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(三)
    WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(四)
    WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(完)
    Backend Serverside Programing (Nginx)
    Sec资产管理——SwebUI开源应用解决方案
    SwebONE 项目还原部署教程
    SWebONE ,OA办公——SwebUI开源应用解决方案
    使用activityViewModels()或viewModels()报错的原因
    Inheritance from an interface with '@JvmDefault' members is only allowed with Xjvmdefault option
    Android Studio终端通过命令在gitlab上创建分支
  • 原文地址:https://www.cnblogs.com/tszr/p/15310854.html
Copyright © 2020-2023  润新知