springboot2原理实战(16)--jdbc数据源和事务

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: springboot2原理实战(16)--jdbc数据源和事务

目录:


本文主要记录下springboot

5d4c6812c8535adbb050f4ddf2e1bce8.png


一、jdbc操作mysql


使用jdbc的话,前提示导入springboot的jdbc的jar


<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>


1.加入数据库驱动


<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.45</version>
    <scope>runtime</scope>
</dependency>


2.加入配置在application.properties


spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456


3.测试是否加入数据源


@SpringBootApplication
public class Demo16Application {
    public static void main(String[] args) throws SQLException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        DataSource dataSource= context.getBean(DataSource.class);
        System.out.println(dataSource);
//        System.out.println(context.getBean(DataSourceProperties.class));
        System.out.println(dataSource.getConnection());
        //打印出数据库名字 springboot装配好的dataSource
        System.out.println(dataSource.getConnection().getCatalog());
//        System.out.println(dataSource.getDataUsername());
    }


如下图: 显示已经获取了springboot2默认的数据源和我们自建的mysql的数据库名称为springboot

46a9d80a6e05e4e3b19d57a0ee70bcdf.png

以上操作,springboot会自动装配好DataSource,JdbcTemplate可以直接使用。


3.测试mysql的新增数据


@Repository
public class ProductDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public void addProduct(String name){
        //注意有sql注入的风险
        String sql = "insert into product(name) values('"+name+"')";
        jdbcTemplate.execute(sql);
    }
    public void addProductBatch(String ... names) throws FileNotFoundException {
       for (String name: names){
           //注意有sql注入的风险
           String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new FileNotFoundException();
            }
        }
        add(names);
    }
    public void add(String ... names){
        for (String name: names){
            //注意有sql注入的风险
            String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new NullPointerException();
            }
        }
    }
}


@SpringBootApplication
public class Demo16Application {
    public static void main(String[] args) throws SQLException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        System.out.println(context.getBean(JdbcTemplate.class));
        context.getBean(ProductDao.class).addProduct("TV");
    }
 }


查询数据库,显示数据已经加入:


二、数据源切换:


1.springboot内置的数据源和默认的数据源是什么:


springboot内置的数据源有5种,在DataSourceAutoConfiguration下:


spring2默认开启的是DataSourceConfiguration.Hikari.class的数据源,我们打印数据源看下:


@SpringBootApplication
public class Demo16Application {
    public static void main(String[] args) throws SQLException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        DataSource dataSource= context.getBean(DataSource.class);
        System.out.println(dataSource);
    }


打印结果如下图:显示默认的是tomcat数据源:


1dc618a0ed9580ce8bfa6facb208c08f.png


2.springboot切换内置的数据源:


方式1:jar包+配置文件配置实现


pom中添加:


<dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </dependency>


我们可以使用:pring.datasource.type切换数据源:


在spring.properties下配置:


spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource


入口函数再次打印:


@SpringBootApplication
public class Demo16Application {
    public static void main(String[] args) throws SQLException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        DataSource dataSource= context.getBean(DataSource.class);
        System.out.println(dataSource);
        System.out.println(context.getBean(DataSourceProperties.class));
        }
 }


如下图:显示数据源已经切换:


1dc618a0ed9580ce8bfa6facb208c08f.png


方式2:通过排除+jar包


pom中添加:


<dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </dependency>
1


同时排除默认的数据源


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jdbc</artifactId>
     <exclusions>
         <exclusion>
             <groupId>com.zaxxer</groupId>
             <artifactId>HikariCP</artifactId>
         </exclusion>
     </exclusions>
</dependency>


运行测试:如下图,说明也切换成了tomcat数据源。


1dc618a0ed9580ce8bfa6facb208c08f.png


2.配置自己的的数据源 阿里的druid。


只要装配一个DataSource到spring容器中即可。


1)添加jar包


在pom中添加druid的jar包


<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.20</version>
</dependency>


测试:


application.properties中写个数据库地址:


spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456


2)配置方式注入数据源


@SpringBootConfiguration
public class DBConfiguration {
    @Autowired
    private Environment env;
    @Bean
    public DataSource createDataSource(){
        DruidDataSource  ds = new DruidDataSource();
        ds.setUrl(env.getProperty("spring.datasource.url"));
        ds.setUsername(env.getProperty("spring.datasource.username"));
        ds.setPassword(env.getProperty("spring.datasource.password"));
        ds.setDriverClassName(env.getProperty("spring.datasource.driverClassName"));
        return ds;
    }
}


3)测试


入口函数中:


public static void main(String[] args) throws SQLException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        DataSource dataSource = context.getBean(DataSource.class);
        // 默认的数据源; class com.zaxxer.hikari.HikariDataSource
        System.out.println(dataSource.getClass());
        context.close();
    }


运行结果如下:显示已经成为了我们自定义的数据源。

1dc618a0ed9580ce8bfa6facb208c08f.png


三、事务


springboot2使用事务的方式很简单:


1.步骤:


1.在启动类上首先使用@@EnableTransactionManagement启用对事务的支持


2.在需要使用事物的方法上面加上@Transactional


举例说明:

@EnableTransactionManagement
@SpringBootApplication
public class Demo16Application {
    //测试事务
    public static void main4(String[] args) throws FileNotFoundException {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        System.out.println(context.getBean(JdbcTemplate.class));
        context.getBean(ProductDao.class).addProductBatch("TV","MP3","MP4");
    }
    }


@Repository
public class ProductDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;  
   @Transactional
    public void addProductBatch(String ... names) {
        for (String name: names){
            //注意有sql注入的风险
            String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new RuntimeException("异常");
            }
        }


可以看到当我们插入MP4应该全部回滚,看下是否能达到预期效果,运行入口函数。

看下数据库,有没有插入:

1dc618a0ed9580ce8bfa6facb208c08f.png

显示没有插入,说明事务成功。


2.特别注意: 默认只会对运行时异常进行事务回滚,非运行时异常不会回滚事务。


我们可以测试下:


@Repository
public class ProductDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
   @Transactional
    public void addProductBatch(String ... names) throws Exception {
        for (String name: names){
            //注意有sql注入的风险
            String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new FileNotFoundException();
            }
        }
    }
    }


@EnableTransactionManagement
@SpringBootApplication
public class Demo16Application {
    //测试事务
    public static void main(String[] args) throws Exception {
        ConfigurableApplicationContext context = SpringApplication.run(Demo16Application.class, args);
        System.out.println(context.getBean(JdbcTemplate.class));
        context.getBean(ProductDao.class).addProductBatch("TV","MP3","MP4");
    }
}


结果显示插入了,说明配置的事务失效。

1dc618a0ed9580ce8bfa6facb208c08f.png


3.控制事务回滚策略


上面的注意我们看到了,事务默认值对运行时异常起作用,那么我们怎么让我们的异常都用上事务呢?


我们看下Transactional的源码:

1dc618a0ed9580ce8bfa6facb208c08f.png


transactionManager 对多数据源下情况下有效

rollbackFor设置那些异常进行回滚,默认是运行时异常

noRollbackFor 设置不对那些异常进行回滚,默认是非运行时异常


刚才的案例如果改成:


@Transactional(rollbackFor = Exception.class)
    public void addProductBatch(String ... names) throws Exception {
        for (String name: names){
            //注意有sql注入的风险
            String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new FileNotFoundException();
            }
        }
    }


删除掉数据,再测试下:

1dc618a0ed9580ce8bfa6facb208c08f.png

显示回滚正常了。


4.特别注意2: 只对方法上加@Trancational的方法内的jdbc操作事务有效


只对方法上加@Trancational的方法内的jdbc操作事务有效,调用子方法,子方法上有这个注释无效。


测试下:


@Repository
public class ProductDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
  //直接调用的方法没加@Transactional注解,看下效果
    public void addProductBatch(String ... names) throws Exception {
       add(names);
    }
    @Transactional(rollbackFor = Exception.class)
    public void add(String ... names){
        for (String name: names){
            //注意有sql注入的风险
            String sql = "insert into product(name) values('"+name+"')";
            jdbcTemplate.execute(sql);
            if("MP4".equals(name)){
                throw new NullPointerException();
            }
        }
    }
    }


运行入口函数,然后看下数据库:


1dc618a0ed9580ce8bfa6facb208c08f.png

结果显示:事务失效,说明在直接调用jdbc操作数据库的方法上加@Transactional,事务才有效。


本篇主要围绕springboot2的jdbc展开讲了操作mysql,数据源的默认的5种,如何切换内置的数据源,定义自己的数据源,和事务的相关使用和注意事项。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
XML Java 开发者
Spring Boot开箱即用可插拔实现过程演练与原理剖析
【11月更文挑战第20天】Spring Boot是一个基于Spring框架的项目,其设计目的是简化Spring应用的初始搭建以及开发过程。Spring Boot通过提供约定优于配置的理念,减少了大量的XML配置和手动设置,使得开发者能够更专注于业务逻辑的实现。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,为开发者提供一个全面的理解。
34 0
|
5天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
43 14
|
1月前
|
Java Spring
SpringBoot自动装配的原理
在Spring Boot项目中,启动引导类通常使用`@SpringBootApplication`注解。该注解集成了`@SpringBootConfiguration`、`@ComponentScan`和`@EnableAutoConfiguration`三个注解,分别用于标记配置类、开启组件扫描和启用自动配置。
58 17
|
26天前
|
Java 容器
springboot自动配置原理
启动类@SpringbootApplication注解下,有三个关键注解 (1)@springbootConfiguration:表示启动类是一个自动配置类 (2)@CompontScan:扫描启动类所在包外的组件到容器中 (3)@EnableConfigutarion:最关键的一个注解,他拥有两个子注解,其中@AutoConfigurationpackageu会将启动类所在包下的所有组件到容器中,@Import会导入一个自动配置文件选择器,他会去加载META_INF目录下的spring.factories文件,这个文件中存放很大自动配置类的全类名,这些类会根据元注解的装配条件生效,生效
|
2月前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
227 6
|
2月前
|
Java Spring 容器
springboot @RequiredArgsConstructor @Lazy解决循环依赖的原理
【10月更文挑战第15天】在Spring Boot应用中,循环依赖是一个常见问题,当两个或多个Bean相互依赖时,会导致Spring容器陷入死循环。本文通过比较@RequiredArgsConstructor和@Lazy注解,探讨它们解决循环依赖的原理和优缺点。@RequiredArgsConstructor通过构造函数注入依赖,使代码更简洁;@Lazy则通过延迟Bean的初始化,打破创建顺序依赖。两者各有优势,需根据具体场景选择合适的方法。
104 4
|
3月前
|
Java 应用服务中间件 API
Vertx高并发理论原理以及对比SpringBoot
Vertx 是一个基于 Netty 的响应式工具包,不同于传统框架如 Spring,它的侵入性较小,甚至可在 Spring Boot 中使用。响应式编程(Reactive Programming)基于事件模式,通过事件流触发任务执行,其核心在于事件流 Stream。相比多线程异步,响应式编程能以更少线程完成更多任务,减少内存消耗与上下文切换开销,提高 CPU 利用率。Vertx 适用于高并发系统,如 IM 系统、高性能中间件及需要较少服务器支持大规模 WEB 应用的场景。随着 JDK 21 引入协程,未来 Tomcat 也将优化支持更高并发,降低响应式框架的必要性。
Vertx高并发理论原理以及对比SpringBoot
|
3月前
|
Java 数据库连接 数据库
SpringBoot 整合jdbc和mybatis
本文详细介绍了如何在SpringBoot项目中整合JDBC与MyBatis,并提供了具体的配置步骤和示例代码。首先,通过创建用户实体类和数据库表来准备基础环境;接着,配置Maven依赖、数据库连接及属性;最后,分别展示了JDBC与MyBatis的集成方法及其基本操作,包括增删查改等功能的实现。适合初学者快速入门。
110 3
SpringBoot 整合jdbc和mybatis
|
2月前
|
SQL Java 数据库
Springboot+spring-boot-starter-data-jdbc实现数据库的操作
本文介绍了如何使用Spring Boot的spring-boot-starter-data-jdbc依赖来操作数据库,包括添加依赖、配置数据库信息和编写基于JdbcTemplate的数据访问代码。
203 2
|
3月前
|
Java 开发者 数据格式
【Java笔记+踩坑】SpringBoot基础4——原理篇
bean的8种加载方式,自动配置原理、自定义starter开发、SpringBoot程序启动流程解析
【Java笔记+踩坑】SpringBoot基础4——原理篇
下一篇
DataWorks