当前位置: 首页 >Java技术 > 从jdbc到spring-boot-starter-jdbc

从jdbc到spring-boot-starter-jdbc

从jdbc到spring-boot-starter-jdbc

jdbc 是什么

JDBC是一种用于执行SQL语句的API,可以为多种关系数据库提供统一访问,它是由一组用Java语言编写的类和接口。是Java访问数据库的标准规范。

JDBC是Java提供的一种标准规范,具体的实现由各个数据库厂商去实现。对开发者来说屏蔽了不同数据库之间的区别,可以使用相同的方式(Java API)去操作不同的数据库。两个设备之间要进行通信需要驱动,不同数据库厂商对JDBC的实现类就是去连接数据库的驱动。如mysql-connector-java 连接mysql数据库的驱动。

使用JDBC连接数据库的步骤

  1. 注册驱动,这里的执行 就需要驱动jar包
// mysql 数据库:“com.mysql.jdbc.Driver”Class.forName(driver);
  1. 建立数据库连接 Connection
Connection conn=DriverManager.getConnection(url,userName,password);
  1. 创建Statement对象 用来执行SQL语句
Statement statement =conn.createStatement();
  1. 执行SQL语句
ResultSet rs =statement.executeQuery(sql);
  1. 处理结果
  2. 释放资源

数据库连接池

在使用JDBC进行数据库操作过程中,每次使用就要创建连接,同时使用完毕还必须得关闭连接,操作繁琐容易出错,并且Connection的取得和释放是代价比较高的操作。解决这个问题的方法就是连接池。连接池就是事先取得一定数量的Connection,程序执行处理的时候不是新建Connection,而是取得预先准备好的Connection。

DataSource

提供连接池机能的技术叫做DataSource。DataSource是JDK提供一个标准接口在javax.sql.DataSource包下。常见的DBCP、C3P0、druid等。

spring-boot-starter-jdbc

spring-boot-starter-jdbc主要提供了三个功能,第一个就是对数据源的装配,第二个就是提供一个JdbcTemplate简化使用,第三个就是事务

数据源相关使用

查看数据源和连接信息

package com.lucky.spring;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;@SpringBootApplicationpublic class Application implements CommandLineRunner {Logger logger = LoggerFactory.getLogger(Application.class);@AutowiredDataSource dataSource;public static void main(String[] args) {SpringApplication.run(Application.class, args);}@Overridepublic void run(String... args) throws Exception {System.out.println(">>>>>>>>>>>>>>>>>服务启动执行");showConnection();}private void showConnection() throws SQLException {logger.info("dataSource:{}", dataSource.getClass().getName());Connection connection = dataSource.getConnection();logger.info("connection:{}", connection.toString());}}

代码逻辑如下:

  1. 通过CommandLineRunner监听服务的启动,在启动后调用showConnection方法
  2. 在showConnection方法里打印出当前的DataSource实现类,获取一个连接并打印该连接的基本信息

打印结果如下

>>>>>>>>>>>>>>>>>服务启动执行2020-07-12 07:38:42.076  INFO 8144 --- [main] com.lucky.spring.Application : dataSource:com.zaxxer.hikari.HikariDataSource2020-07-12 07:38:42.077  INFO 8144 --- [main] com.zaxxer.hikari.HikariDataSource: HikariPool-1 - Starting...2020-07-12 07:38:42.274  INFO 8144 --- [main] com.zaxxer.hikari.HikariDataSource: HikariPool-1 - Start completed.2020-07-12 07:38:42.277  INFO 8144 --- [main] com.lucky.spring.Application : connection:HikariProxyConnection@1366499339 wrapping com.mysql.jdbc.JDBC4Connection@25c5e994

可以看到

  1. dataSource使用的是:com.zaxxer.hikari.HikariDataSource
  2. connection信息是:HikariProxyConnection@1366499339 wrapping com.mysql.jdbc.JDBC4Connection@25c5e994

当前的pom文件中仅仅配置了spring-boot-starter-jdbc和mysql数据库驱动

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies>

Springboot支持的数据源

DataSourceAutoConfiguration类的内部类PooledDataSourceConfiguration标识了默认支持的数据源。

@Configuration@Conditional({DataSourceAutoConfiguration.PooledDataSourceCondition.class})@ConditionalOnMissingBean({DataSource.class, XADataSource.class})@Import({Hikari.class, Tomcat.class, Dbcp2.class, Generic.class, DataSourceJmxConfiguration.class})protected static class PooledDataSourceConfiguration {protected PooledDataSourceConfiguration() {}}

默认支持Hikari、Tomcat、Dbcp2、Generic、DataSourceJmxConfiguration这五种数据源。从上面的数据源和连接信息的打印可以知道默认情况下Springboot装配的是Hikari数据源。

自动装配Tomcat数据源

DataSourceConfigurationTomcat数据源的实现如下

	@ConditionalOnClass({org.apache.tomcat.jdbc.pool.DataSource.class})@ConditionalOnMissingBean({DataSource.class})@ConditionalOnProperty(name = {"spring.datasource.type"},havingValue = "org.apache.tomcat.jdbc.pool.DataSource",matchIfMissing = true)static class Tomcat {Tomcat() {}@Bean@ConfigurationProperties(prefix = "spring.datasource.tomcat")public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class);DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());String validationQuery = databaseDriver.getValidationQuery();if (validationQuery != null) {dataSource.setTestOnBorrow(true);dataSource.setValidationQuery(validationQuery);}retu dataSource;}}

让Springboot自动装配选择Tomcat的方式有两种

第一种

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--默认配置 start--><!--<dependency>--><!--<groupId>org.springframework.boot</groupId>--><!--<artifactId>spring-boot-starter-jdbc</artifactId>--><!--</dependency>--><!--默认配置 end--><!--使用tomcat数据源 方式 start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><exclusions><exclusion><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jdbc</artifactId></dependency><!--使用tomcat数据源 方式 end--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies>
  1. 加入tomcat-jdbc数据源的依赖
  2. 排除Hikari的数据源依赖

打印信息如下:

>>>>>>>>>>>>>>>>>服务启动执行2020-07-12 08:11:49.761  INFO 8469 --- [main] com.lucky.spring.Application : dataSource:org.apache.tomcat.jdbc.pool.DataSource2020-07-12 08:11:50.058  INFO 8469 --- [main] com.lucky.spring.Application : connection:ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@4d6f197e]]

第二种

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--默认配置 start--><!--<dependency>--><!--<groupId>org.springframework.boot</groupId>--><!--<artifactId>spring-boot-starter-jdbc</artifactId>--><!--</dependency>--><!--默认配置 end--><!--使用tomcat数据源 方式 start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jdbc</artifactId></dependency><!--使用tomcat数据源 方式 end--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency></dependencies>
spring:  datasource:url: jdbc:mysql://localhost:3306/readinglist?characterEncoding=utf8&useSSL=falseuseame: rootpassword: 12345678type: org.apache.tomcat.jdbc.pool.DataSource
  1. pom文件中添加tomcat-jdbc依赖
  2. 在application.yml文件中指定数据源为org.apache.tomcat.jdbc.pool.DataSource

打印结果如下:

>>>>>>>>>>>>>>>>>服务启动执行2020-07-12 08:15:51.746  INFO 8525 --- [main] com.lucky.spring.Application : dataSource:org.apache.tomcat.jdbc.pool.DataSource2020-07-12 08:15:52.152  INFO 8525 --- [main] com.lucky.spring.Application : connection:ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@5173200b]]

使用druid数据源

对于Springboot默认支持的五种数据源,可以通过上面两种方式(一、排除默认数据源,添加使用的数据源;二、添加使用的数据源,使用配置文件指定使用的数据源) 进行选择使用数据源。如果是其他开源的数据源呢?比如阿里的druid数据源。也是有两种方式。

第一种

  <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.23</version></dependency>
spring:  datasource:url: jdbc:mysql://localhost:3306/readinglist?characterEncoding=utf8&useSSL=falseuseame: rootpassword: 12345678type: com.alibaba.druid.pool.DruidDataSource
  1. 添加druid数据源依赖
  2. 在application.yml文件中指定数据源为com.alibaba.druid.pool.DruidDataSource

打印结果如下:

>>>>>>>>>>>>>>>>>服务启动执行2020-07-12 08:27:52.523  INFO 8813 --- [main] com.lucky.spring.Application : dataSource:com.alibaba.druid.pool.DruidDataSource2020-07-12 08:27:52.562  INFO 8813 --- [main] com.alibaba.druid.pool.DruidDataSource: {dataSource-1} inited2020-07-12 08:27:52.883  INFO 8813 --- [main] com.lucky.spring.Application : connection:com.mysql.jdbc.JDBC4Connection@3b0ca5e1

第二种

  <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.23</version></dependency>
package com.lucky.spring;import com.alibaba.druid.pool.DruidDataSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.Bean;import org.springframework.core.env.Environment;import javax.sql.DataSource;import java.sql.Connection;import java.sql.SQLException;@SpringBootApplicationpublic class Application implements CommandLineRunner {Logger logger = LoggerFactory.getLogger(Application.class);@AutowiredDataSource dataSource;public static void main(String[] args) {SpringApplication.run(Application.class, args);}@Overridepublic void run(String... args) throws Exception {System.out.println(">>>>>>>>>>>>>>>>>服务启动执行");showConnection();}@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/readinglist?characterEncoding=utf8&useSSL=false");dataSource.setUseame("root");dataSource.setPassword("12345678");retu dataSource;}private void showConnection() throws SQLException {logger.info("dataSource:{}", dataSource.getClass().getName());Connection connection = dataSource.getConnection();logger.info("connection:{}", connection.toString());}}
  1. 添加druid依赖
  2. 创建DataSource的bean,进行相关配置后,返回DruidDataSource

打印结果如下:

>>>>>>>>>>>>>>>>>服务启动执行2020-07-12 08:37:09.898  INFO 9140 --- [main] com.lucky.spring.Application : dataSource:com.alibaba.druid.pool.DruidDataSource2020-07-12 08:37:09.951  INFO 9140 --- [main] com.alibaba.druid.pool.DruidDataSource: {dataSource-1} inited2020-07-12 08:37:10.314  INFO 9140 --- [main] com.lucky.spring.Application : connection:com.mysql.jdbc.JDBC4Connection@d400943

JdbcTemplate相关使用

JdbcTemplate 是什么

Spring对数据库的操作在jdbc上面做了深层次的封装。使用Spring的注入功能,可以把DataSource注册到JdbcTemplate之中。

JdbcTemplate主要提供了一下五类方法

  1. execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句
  2. update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句
  3. query方法及queryForXXX方法:用于执行查询相关语句
  4. call方法:用于执行存储过程、函数相关语句

事务的相关使用

Springboot中在需要使用事务的方法上面添加@Transactional,需要注意的是,默认只会对运行时异常进行事务回滚,非运行时异常不会回滚事务。

Controller层定义了两个接口

@RestControllerpublic class DataOperationController {@AutowiredDataOpeService service;@GetMapping("/api/queryData")public String queryData() {retu service.queryData();}@PostMapping("/api/addData")public String addData() {try {service.addData();retu "add data success";} catch (Exception e) {e.printStackTrace();retu "add data fail";}}}

Service通过JdbcTemplate执行sql

@Servicepublic class DataOpeServiceImpl implements DataOpeService {private Logger logger = LoggerFactory.getLogger(DataOpeServiceImpl.class);@Autowiredprivate JdbcTemplate template;@Overridepublic String queryData() {String sql = "select * from t where id=1";RowMapper<T> data = new BeanPropertyRowMapper<>(T.class);T t = template.queryForObject(sql, data);retu t.toString();}@Overridepublic String addData() {List<T> data = new ArrayList<>();for (int i = 0; i < 2; i++) {T item = new T();item.setA(i);item.setB(i);data.add(item);}for (int i = 0; i < data.size(); i++) {String sql = "insert into t(a,b) values (" + data.get(i).getA() + "," + data.get(i).getB() + ")";logger.info("sql:{}", sql);template.execute(sql);}retu null;}}

运行时异常

修改代码,人为在添加第二条记录时抛出异常。

  @Transactional@Overridepublic String addData() {List<T> data = new ArrayList<>();for (int i = 0; i < 2; i++) {T item = new T();item.setA(i);item.setB(i);data.add(item);}for (int i = 0; i < data.size(); i++) {String sql = "insert into t(a,b) values (" + data.get(i).getA() + "," + data.get(i).getB() + ")";logger.info("sql:{}", sql);if (data.get(i).getA() == 1) {throw new NullPointerException("人为抛出运行时异常异常");}template.execute(sql);}retu null;}

调用接口,发现事务生效,即发生运行时异常进行了代码回滚。

非运行时异常

重新修改代码,人为抛出非运行时异常。

@Transactional@Overridepublic String addData() throws Exception{List<T> data = new ArrayList<>();for (int i = 0; i < 2; i++) {T item = new T();item.setA(i);item.setB(i);data.add(item);}for (int i = 0; i < data.size(); i++) {String sql = "insert into t(a,b) values (" + data.get(i).getA() + "," + data.get(i).getB() + ")";logger.info("sql:{}", sql);if (data.get(i).getA() == 1) {//throw new NullPointerException("人为抛出运行时异常异常");throw new FileNotFoundException("人为抛出非运行时异常");}template.execute(sql);}retu null;}

调用接口,发现事务没有生效,即第一条数据插入到了数据库里。

指定回滚时的异常

如果要使得非运行时期异常也回滚,那么在使用@Transactional注解时,指定rollbackFor属性。

	@Transactional(rollbackFor = Exception.class)@Overridepublic String addData() throws Exception{List<T> data = new ArrayList<>();for (int i = 0; i < 2; i++) {T item = new T();item.setA(i);item.setB(i);data.add(item);}for (int i = 0; i < data.size(); i++) {String sql = "insert into t(a,b) values (" + data.get(i).getA() + "," + data.get(i).getB() + ")";logger.info("sql:{}", sql);if (data.get(i).getA() == 1) {//throw new NullPointerException("人为抛出运行时异常异常");throw new FileNotFoundException("人为抛出非运行时异常");}template.execute(sql);}retu null;}

作者:在线打工者
来源链接:https://www.cnblogs.com/lucky9322/p/13289662.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/java/113301.html

标签:JDBC
分享给朋友:

“从jdbc到spring-boot-starter-jdbc” 的相关文章