spring基础05-事务

5 事务

5.1 搭建事务操作环境(以银行转账为例)

  1. 创建数据库,一个表t_acount,仨字段 id,username,money

  2. 创建service,dao,完成对象创建和注入关系

    • service里面注入dao,dao里面注入jdbcTemoplate,jdbcTemplate里面注入Datesource
  3. dao创建俩方法,一个多钱的,一个少钱的

    • @Repository
      public class UserDaoImpl implements UserDao{
          @Autowired
          private JdbcTemplate jdbcTemplate;
          
          @Override
          public void addMoney() {
              String sql="update t_acount set money=money+? where username=?";
              jdbcTemplate.update(sql,100,"张大壮");
          }
      
          @Override
          public void reduceMoney() {
              String sql="update t_acount set money=money-? where username=?";
              jdbcTemplate.update(sql,100,"李二狗");
          }
      }
      
  4. service创建转账方法

    • @Service
      public class UserService {
          @Autowired
          private UserDao userDao;
      
          public void acountMoney(){
              userDao.addMoney();
              //来一个异常
              int x=10/0;
              userDao.reduceMoney();
          }
      }
      
  5. 测试类

    • @Test
      public void test1(){
          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-base.xml");
          UserService userService = context.getBean("userService", UserService.class);
          userService.acountMoney();
      }
      

问题:不满足原子性

比如service的方法中,两次转账之间发生一个异常

5.2 事务管理

  • 事务应该添加在service层

  • 在sping中做事务管理操作有两种

    • 一种是编程式事务管理,和声明式事务管理
  • 声明式事务管理 底层用的就是AOP

    • 注解方法
    • xml配置文件方法
  • spring事务管理的API

    • 提供一个接口,代表事务管理器,这个接口针对不同的矿建提供不同的实现类
    • image

5.3 声明式事务管理(注解)

5.3.1 具体实现

  1. spring中配置事务管理器 ,人话:xml创建事务管理器类的对象

    • 想看完全注解的,去5.5

    • <!--创建事务管理器-->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <!--注入数据源-->
          <property name="dataSource" ref="druidDataSource"></property>
      </bean>
      
  2. spring配置文件中,开启事务注解

    • 略,同之前在xml中天健aop,context的空间一样,添加一个tx

    • 开启事务注解

    • <!--开启事务注解-->
      <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
      
  3. 在service类上面,或者类里的方法上面添加事务注解

    • @Transactional

    • @Service
      public class UserService {
          @Autowired
          private UserDao userDao;
          @Transactional
          public void acountMoney(){
                  userDao.addMoney();
                  int x=10/0;
                  userDao.reduceMoney();
          }
      }
      

5.3.2 @Transaction注解

所有的参数

image

  • Propagation 事务传播行为

    • 多个事务方法(改变数据库内容的方法)直接进行调用,这个过程中事务是如何进行管理的

    • /**
       * The transaction propagation type.
       * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
       */
      Propagation propagation() default Propagation.REQUIRED;
      
    • 常用的就前俩

    • image

  • ioslation 事务隔离级别

    • 为了解决事务的隔离性:保证多事务操作之间不会产生影响
    • image
  • timeout 超时时间

    • 事务需要在一个规定时间内提交,提交不上就会rollback,
    • 默认值-1,不超时,可以自己设置,单位为s
  • readOnly 是否只读

    • 设置成true之后,就不能做修改操作了
    • 默认false
  • rollbackFor 回滚

    • 设置事务出现了哪些异常时进行事务回滚
  • noRollbackFor 不会滚

    • 设置出现了哪些异常时不回滚

5.4 声明式事务管理(XML)

一键略过,但是面试可能问。。。

<!--1创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
    <property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txaddvice">
    <!--配置事务的一些相关参数-->
    <tx:attributes>
        <!--指定在哪种规则的方法上面添加事务-->
        <tx:method name="accountMoney"/><!--全匹配-->
        <tx:method name="acount*"/><!--正则匹配-->
    </tx:attributes>
</tx:advice>
<!--3 切入点和切面-->
<aop:config>
    <!--配置切入点-->
    <aop:pointcut id="pt" expression="execution(* com.zhang.service.UserService.*(..))"/>
    <!--配置切面-->
    <aop:advisor advice-ref="txaddvice" pointcut-ref="pt"></aop:advisor>
</aop:config>

5.5 声明式事务管理(完全注解)

1.创建配置类,使用配置类代替配置文件

@Configuration//这是个配置类
@ComponentScan(basePackages = "com.zhang")//组件扫描o
@EnableTransactionManagement//开启事务管理
public class TxConfig {
    //创建数据库的连接池
    @Bean
    public DruidDataSource getDruidDataSOurce(){
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///user_db?useUnicode=true&ampcharacterEncodign=UTF-8&serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("xxxx");
        return dataSource;
    }

    @Bean
    public JdbcTemplate getJbdcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate=new JdbcTemplate();
        //注入datasource
        //方法1:空参,然后直接调用上面的方法
        //jdbcTemplate.setDataSource(getDruidDataSOurce());
        //这里IOC容器不会创建多个datasource

        //方法2:
        //带参数DataSource dS ,然后把dS传进去
        jdbcTemplate.setDataSource(dataSource);
        //到IOC容器中根据类型自动找到,Datasource对象
        return jdbcTemplate;
    }
	//创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dstm = new DataSourceTransactionManager();
        dstm.setDataSource(dataSource);
        return dstm;
    }
}

赶紧开始看springboot吧,,这些就都不用写了

6 Spring5新功能

整个Spring 5 是基于jdk8开发,兼容jdk9

很多过时的方法都删除了,

6.1 使用log4j2

  • spring5 自带了通用的日志封装
  • 也可以整合log4j等三方工具
  • 已经移除了Log4jConfigListener,官方建议使用Log4j

配置文件名是固定的log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: (优先级低,显示内容少) OFF>FATAL>ERROR > WARN > INFO > DEBUG > TRACE > ALL 优先级高,显示详细 -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<configuration status="INFO">
    <!--先定义所有的appender-->
    <appenders>
        <!--这个输出控制台的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} 【%t】 %-5level %logger{36} - %msg%n"/>
        </console>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>

6.2 @Nullable注解

@Nullable注解可以使用在方法上面,属性上面,参数上麦你,表示方法返回可以为欧空,属性值可以为空,参数值可以为空

6.3 核心容器支持函数风格创建对象 (Lamda)

原因:spring管理的对象都是spring自己创建的,如果是new了一个对象,那么spring是不知道的,就无法管理

需要在spring中注册

@Test
public  void test3(){
    //1.创建GenericApplicationContext对象
    GenericApplicationContext context = new GenericApplicationContext();
    //2.调用共context的方法对象注册
    context.refresh();
    context.registerBean(UserDaoImpl.class,()->new UserDaoImpl() {});//第一个参数就是@Nullable的,可以指定beanname
    //context.registerBean("user111",UserDaoImpl.class,()->new UserDaoImpl() {});
    
   //3.获取在spring注册的对象
    UserDaoImpl user = (UserDaoImpl) context.getBean("com.zhang.dao.UserDaoImpl");
    //UserDaoImpl user = (UserDaoImpl) context.getBean("user111");//上面如果指定了,就可以直接使用
    
    System.out.println(user);
}

6.4 测试Junit5

6.4.1 整合JUnit4

  1. 引入依赖

    • spring-test
  • 创建测试类,使用注解方式

  • @RunWith(SpringJUnit4ClassRunner.class)//指定单元测试矿建
    @ContextConfiguration("classpath:bean-base.xml")//加载配置文件
    public class Junit4Test {
    
        @Autowired
        private UserService userService;//等用于之前的遗传classpathxml...context...getbean...userService;
    
        @Test
        public void test1(){
            userService.acountMoney();
        }
    }
    

6.4.2 整合JUnit5

  • 引入JUnit5 jar包

  • @ExtendWith(SpringExtension.class)
    @ContextConfiguration("classpath:bean-base.xml")
    //或者是使用这个使用复合注解替代上面的俩
    @SpringJUnitConfig(locations = "bean-base.xml")
    public class Junit5Test {
        @Autowired
        private UserService userService;//等用于之前的遗传classpathxml...context...getbean...userService;
        @Test
        public void test1(){
            userService.acountMoney();
        }
    }
    
posted @   荧惑微光  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示