Spring使用——JDBCTemplate+事务管理篇

JDBCTemplate

Spring中为开发者提供了对JDBC进行操作的存取框架

所需的依赖

    <!-- spring-jdbc包括了一些如jdbcTemplate的工具类 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring-version}</version>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring-version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>

数据源配置

这里使用的是阿里的数据库连接池的包

    <context:property-placeholder location="datasource.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driverClassName}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${account}"/>
        <property name="password" value="${password}"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

datasource.properties 

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/employees?serverTimezone=UTC
account = root
password = 123456

建立连接

public class MyJDBCTemplate {
    public static void main(String[] args) throws SQLException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        String sql = "select * from employees";
        RowMapper<Employee> employeeRowMapper = new BeanPropertyRowMapper<>(Employee.class);
        List<Employee> employees = jdbcTemplate.query(sql,employeeRowMapper);
        System.out.println(employees.size());

    }
}

数据库表

Employee类

public class Employee {
    private Integer emp_no;
    private String first_name;

    public Integer getEmp_no() {
        return emp_no;
    }

    public void setEmp_no(Integer emp_no) {
        this.emp_no = emp_no;
    }

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }
}

事务管理

编程式事务管理需要将事务管理代码嵌入业务代码中控制事务的提交和回滚。但这样会将事务管理代码与业务代码混在一起,也会造成代码的冗余

而Spring中的事务管理采用的是声明式事务管理,横向抽取吃事务管理代码,通过AOP实现声明式事务管理

具体实现通过增加一个事务管理器+注解的形式

操作步骤

1.配置事务管理器

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

2.1开启注解驱动

<tx:annotation-driven transaction-manager="transactionManager"/>

2.2配置文件方式

<tx:advice id="txAdvice" transaction-manager="txManager"> 
      <tx:attributes>  
      <!--设置所有匹配的方法,然后设置传播级别和事务隔离-->
           <tx:method name="save*" propagation="REQUIRED" /> 
           <tx:method name="add*" propagation="REQUIRED" /> 
           <tx:method name="create*" propagation="REQUIRED" /> 
           <tx:method name="insert*" propagation="REQUIRED" /> 
           <tx:method name="update*" propagation="REQUIRED" /> 
           <tx:method name="merge*" propagation="REQUIRED" /> 
           <tx:method name="del*" propagation="REQUIRED" /> 
           <tx:method name="remove*" propagation="REQUIRED" /> 
           <tx:method name="put*" propagation="REQUIRED" /> 
           <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> 
           <tx:method name="count*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="list*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="*" propagation="SUPPORTS" read-only="true" /> 
     </tx:attributes> 
</tx:advice> 

3.@Transactional

被注解的方法/类内所发生的一切操作都会被认为式一次事务,如果出现指定异常报错就会事务回滚

关于事务回滚的触发条件可以参考这篇文章

https://blog.csdn.net/u011861874/article/details/81542767

事务的属性

  • propagation:事务的传播级别
  • isolation:事务的隔离级别
  • timeout:回滚前可以等待的时间(秒)
  • readonly:只读
  • rollbackFor:指定触发回滚的异常类型
  • noRollbackFor:指定不触发回滚的异常类型
  • rollbackForClassName:指定触发回滚的异常类名
  • noRollbackForClassName:指定不触发回滚的异常类名

1.propagation

Spring中的7个事务传播行为:

事务行为说明
REQUIRED 支持当前事务,假设当前没有事务。就新建一个事务
SUPPORTS

支持当前事务,假设当前没有事务,就以非事务方式运行

MANDATORY支持当前事务,假设当前没有事务,就抛出异常
REQUIRES_NEW 新建事务,假设当前存在事务。把当前事务挂起。两个事务的回滚不会影响对方事务的提交
NOT_SUPPORTED以非事务方式运行操作。假设当前存在事务,就把当前事务挂起。
NEVER以非事务方式运行,假设当前存在事务,则抛出异常
NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与
REQUIRED类似的操作。

 

每个级别的说明我们可以参考https://blog.csdn.net/qq_38526573/article/details/87898161

2.隔离级别

  • 读未提交
  • 读已提交
  • 可重复读
  • 串行化
隔离级别详述
读未提交A事务在执行期间可以读到B事务未提交但已修改的数据。会造成脏读(B事务一旦回滚,数据修改就是无效的,但是A已经开始用了)
读已提交A事务在执行期间可以读到B事务修改的提交了的数据。会造成数据不一致即不可重复读(B事务一旦提交,A事务如果在B提交的先后进行过两次数据读取,会出现数据不一致性的问题)
可重复读A事务在执行期间读到的数据不会发生变化。但会造成幻读(可重复读的原理是对数据记录进行上锁,其他数据无法操作数据,但是不影响其他事务提交新的数据记录,而事务A在执行过程中还是可以读取到事务B新增的记录,也就是我们所说的幻读。事务执行过程中,数据的记录条数不一致,像幻觉一样)
串行化独占式读取,当作单线程即可,安全级别最高,但是性能太低了,并发下基本属于瘫痪

 

3.readonly

指定当前事务操作为只读,通知数据库不需要加锁。但是并不意味着真的是只读,所以需要开发者自己把关。如果出现修改,但是我们声明为只读,就以为mysql不会上锁其他事务依旧可以修改我们读取的数据,就会造成脏读。

 

事务管理也是基于aop编程,但Spring中关于事务的切面都已写好封装完成,我们只需要配置

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原来是肖某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值