【小家Spring】Spring-jdbc的使用以及Spring事务管理的8种方式介绍(声明式事务+编程式事务)(上)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【小家Spring】Spring-jdbc的使用以及Spring事务管理的8种方式介绍(声明式事务+编程式事务)(上)

前言


前面已经讲述了Spring Aop的原理以及源码分析~


若对Spring AOP还不是太了解的话,强烈建议出门左拐,先掌握AOP相关内容,因为Spring的事务管理就是基于Spring AOP实现的


本文主要讲解Spring-JDBC的使用以及它对事务的管理。

主要分为两大块:


1.Spring对jdbc的支持


2.Spring对事务的支持


源码展示基于Spring版本号为:5.1.6.RELEASE 下同下同下同

源码展示基于Spring版本号为:5.1.6.RELEASE 下同下同下同

源码展示基于Spring版本号为:5.1.6.RELEASE 下同下同下同


环境准备


Pom里导入相关jar(基于之前的工程基础上导包):

        <!-- 链接数据库  此处若你的MySql是8.0+版本,请使用8.0+版本的MySql驱动程序-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <!-- 含有spring-tx/core/beans等必须包  所有spring-tx可以不用再单独导入了-->
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.framework.version}</version>
        </dependency>


配置文件:


@Configuration
public class JdbcConfig {
    // 此处只是为了演示 所以不用连接池了===========生产环境禁止这么使用==========
    @Bean
    public DataSource dataSource() {
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setURL("jdbc:mysql://localhost:3306/jedi");
        return dataSource;
    }
     为了执行sql方便 此处采用JdbcTemplate进行===========
    // 生产环境一下一般我们不需要此配置,因为一般我们会使用ORM框架~
    // 但是如果是SpringBoot,这两个类默认都会配置上(导入了Spring-JDBC的jar即可)  比如MyBatis就是基于JDBC的
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}


测试连接是否通畅:


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class, JdbcConfig.class})
public class TestSpringBean {
    @Autowired
    private DataSource dataSource;
    @Test
    public void test1() throws SQLException {
        System.out.println(dataSource); // com.mysql.jdbc.jdbc2.optional.MysqlDataSource@650eab8
        System.out.println(dataSource.getConnection()); // com.mysql.jdbc.JDBC4Connection@72bc6553
        System.out.println(jdbcTemplate); //org.springframework.jdbc.core.JdbcTemplate@66982506
        System.out.println(namedParameterJdbcTemplate); //org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate@70cf32e3
    }
}

Spring JDBC


为了使JDBC更加易于使用,Spring 在 JDBC API 上定义了一个抽象层,以此建立一个 JDBC 存取框架


说明:

在实际开发中,我们DAO层一般都会使用ORM框架(Mybatis,hibernate)等。在有些特殊的情况下,ORM框架的搭建略显笨重(比如下面我们演示Spring事务的时候)。这时最好的选择就是Spring中的jdbcTemplate了


JdbcTemplate和NamedParameterJdbcTemplate


jdbcTemplate提供的主要方法


1.execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;


2.update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;

batchUpdate方法用于执行批处理相关语句;


3.query方法及queryForXXX方法:用于执行查询相关语句;


4.call方法:用于执行存储过程、函数相关语句


Demo:


    @Test
    public void test1() throws SQLException {
        String sql = "select * from user where id = ?";
        // 默认情况下:它就是使用的PreparedStatement,所以不用担心Sql注入问题的
        RowMapper<User> rowMapper = new BeanPropertyRowMapper<>(User.class);
        List<User> list = jdbcTemplate.query(sql, rowMapper, 1);
        User user = jdbcTemplate.queryForObject(sql, rowMapper, 1);
        System.out.println(list);
        System.out.println(user);
    }


NamedParameterJdbcTemplate提供的主要方法


在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制. 定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定,否则就绑定错了


在 Spring JDBC 框架中, 绑定 SQL 参数的另一种选择是使用具名参数(named parameter).

具名参数: SQL 按名称(以冒号开头)而不是按位置进行指定. 具名参数更易于维护, 也提升了可读性. 具名参数由框架类在运行时用占位符取代


NamedParameterJdbcTemplate:是Spring2.0提供的,比JdbcTemplate出现得晚。它可以使用全部jdbcTemplate方法

// @since 2.0
public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations {
  // 它持有一个JdbcTemplate的引用,所以它能够执行它所有的方法
  private final JdbcOperations classicJdbcTemplate;
  ...
}


Demo Show:


    @Test
    public void test1() throws SQLException {
        String sql = "insert into user (name,age) values (:name,:age)";
        User u = new User();
        u.setName("fsx2");
        u.setAge(20);
        SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(u);
        // 不需要id使用这个方法
        //namedParameterJdbcTemplate.update(sql,sqlParameterSource);
        // 这个可议把id输出出来
        KeyHolder keyHolder = new GeneratedKeyHolder();
        namedParameterJdbcTemplate.update(sql, sqlParameterSource, keyHolder);
        int k = keyHolder.getKey().intValue();
        System.out.println(k); //2  id就为2
    }

NamedParameterJdbcTemplate和JdbcTemplate有KeyHolder类,使用它我们可以获得主键,类似Mybatis中的useGeneratedKeys。


因为整体上直接使用JdbcTemplate来操作数据库的可能性几乎没有,所以此处只做一个简单的介绍,重点是后面的Spring事务的讲解~~


Spring事务


事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。


通常情况下,如果在事务中抛出了未检查异常(继承自 **RuntimeException** 的异常),则默认将回滚事务。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。这通常也是大多数开发者希望的处理方式,也是 EJB 中的默认处理方式


事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。


数据库向用户提供保存当前程序状态的方法,叫事务提交(commit);当事务执行过程中,使数据库忽略当前的状态并回到前面保存的状态的方法叫事务回滚(rollback)


Spring配置文件中关于事务配置总是由三个组成部分:


1.DataSource


2.TransactionManager


3.动态代理(核心内容)


DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化。DataSource实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager(MyBatis还是使用的DataSourceTransactionManager)

Spring Framework对事务管理提供了一致的抽象,其特点如下:


  • 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
  • 支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用
  • 提供比其他事务API如JTA更简单的编程式事务管理API
  • 与spring数据访问抽象的完美集成


下面示例的事务管理器通知配置为:


@Configuration
public class JdbcConfig {
  ...
    // ==============Spring事务相关配置~~~==================
    // 必须配置一个事务管理器:此处用的DataSourceTransactionManager来管理事务~~~
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);
        return dataSourceTransactionManager;
    }
    ...
}


业务类为:


public interface HelloService {
    Object hello();
}
@Service
public class HelloServiceImpl implements HelloService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public Object hello() {
        // 向数据库插入一条记录
        String sql = "insert into user (name,age) values ('fsx',21)";
        jdbcTemplate.update(sql);
        // 做其余的事情  可能抛出异常
        System.out.println(1 / 0);
        return "service hello";
    }
}



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
28天前
|
Java 关系型数据库 MySQL
Spring事务失效,我总结了这7个主要原因
本文详细探讨了Spring事务在日常开发中常见的七个失效原因,包括数据库不支持事务、类不受Spring管理、事务方法非public、异常被捕获、`rollbackFor`属性配置错误、方法内部调用事务方法及事务传播属性使用不当。通过具体示例和源码分析,帮助开发者更好地理解和应用Spring事务机制,避免线上事故。适合所有使用Spring进行业务开发的工程师参考。
25 2
|
29天前
|
Java 程序员 Spring
Spring事务的1道面试题
每次聊起Spring事务,好像很熟悉,又好像很陌生。本篇通过一道面试题和一些实践,来拆解几个Spring事务的常见坑点。
Spring事务的1道面试题
|
2月前
|
Java Spring
Spring 事务传播机制是什么?
Spring 事务传播机制是什么?
22 4
|
1月前
|
监控 Java 数据库
Spring事务中的@Transactional注解剖析
通过上述分析,可以看到 `@Transactional`注解在Spring框架中扮演着关键角色,它简化了事务管理的复杂度,让开发者能够更加专注于业务逻辑本身。合理运用并理解其背后的机制,对于构建稳定、高效的Java企业应用至关重要。
41 0
|
3月前
|
XML Java 数据库
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
这篇文章是Spring5框架的实战教程,详细介绍了事务的概念、ACID特性、事务操作的场景,并通过实际的银行转账示例,演示了Spring框架中声明式事务管理的实现,包括使用注解和XML配置两种方式,以及如何配置事务参数来控制事务的行为。
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
|
5月前
|
XML Java 数据库
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
Spring5系列学习文章分享---第五篇(事务概念+特性+案例+注解声明式事务管理+参数详解 )
29 0
|
Java 数据库连接 API
请解释Spring中的声明式事务管理是如何工作的?
在Spring框架中,声明式事务管理是通过使用AOP(面向切面编程)和事务拦截器来实现的。声明式事务管理允许开发者通过在方法或类级别上添加注解来定义事务的行为,而无需显式地编写事务管理的代码。
请解释Spring中的声明式事务管理是如何工作的?
|
XML Java 测试技术
【Spring学习笔记 九】Spring声明式事务管理实现机制(下)
【Spring学习笔记 九】Spring声明式事务管理实现机制(下)
101 0
|
NoSQL Java 关系型数据库
【Spring学习笔记 九】Spring声明式事务管理实现机制
【Spring学习笔记 九】Spring声明式事务管理实现机制
89 0
|
Java 数据库 Spring
Spring学习(十一):声明式事务管理(响应式)
什么是事务:事务是数据库操作的最基本单元,逻辑上一组操作,要么都成功,如果有一个失败则意味着所有操作都失败
159 0
Spring学习(十一):声明式事务管理(响应式)