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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【小家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";
    }
}



相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
Java 数据库 开发者
|
1天前
|
Java 关系型数据库 数据库
Spring Boot多数据源及事务管理:概念与实战
【4月更文挑战第29天】在复杂的企业级应用中,经常需要访问和管理多个数据源。Spring Boot通过灵活的配置和强大的框架支持,可以轻松实现多数据源的整合及事务管理。本篇博客将探讨如何在Spring Boot中配置多数据源,并详细介绍事务管理的策略和实践。
38 3
|
1天前
|
SQL Java 关系型数据库
JDBC编程
JDBC编程
11 2
|
1天前
|
SQL Java 关系型数据库
Spring 事务
Spring 事务
12 1
|
1天前
|
Java 数据库连接 数据库
Spring事务简介,事务角色,事务属性
Spring事务简介,事务角色,事务属性
18 2
|
1天前
|
Java 数据库连接 数据库
16:事务-Java Spring
16:事务-Java Spring
29 5
|
1天前
|
消息中间件 Java 关系型数据库
Spring事务与分布式事务
这篇文档介绍了事务的概念和数据库事务的ACID特性:原子性、一致性、隔离性和持久性。在并发环境下,事务可能出现更新丢失、脏读和不可重复读等问题,这些问题通过设置事务隔离级别(如读未提交、读已提交、可重复读和序列化)来解决。Spring事务传播行为有七种模式,影响嵌套事务的执行方式。`@Transactional`注解用于管理事务,其属性包括传播行为、隔离级别、超时和只读等。最后提到了分布式事务,分为跨库和跨服务两种情况,跨服务的分布式事务通常通过最终一致性策略,如消息队列实现。
|
1天前
|
Java 关系型数据库 MySQL
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
|
1天前
|
监控 Java 测试技术
Spring Boot与事务钩子函数:概念与实战
【4月更文挑战第29天】在复杂的业务逻辑中,事务管理是确保数据一致性和完整性的关键。Spring Boot提供了强大的事务管理机制,其中事务钩子函数(Transaction Hooks)允许开发者在事务的不同阶段插入自定义逻辑。本篇博客将详细探讨事务钩子函数的概念及其在Spring Boot中的应用。
37 1
|
1天前
|
XML Java 数据库连接
精妙绝伦:玩转Spring事务编程的艺术
【4月更文挑战第20天】
31 0