前面介绍了Spring Boot 中的整合Mybatis并实现增删改查、如何实现事物控制。不清楚的朋友可以看看之前的文章。
Spring Boot 除了Mybatis数据库框架,还有JdbcTemplate等数据库操作框架,同样也比较简单实用,如果是一般简单的项目,用JdbcTemplate完全可以实现相关的数据库操作。它虽然没有MyBatis功能强大,但使用比较简单,JdbcTemplate应该算是最简单的数据持久化方案,所以下面就来给大家介绍Spring Boot 使用JdbcTemplate操作数据库,配置多数据源!
一、JDBC简介
JDBC(Java Data Base Connectivity, Java 数据库连接)是一种用于执行各种数据库操作的 API,可以为多种数据库提供统一访问接口。所以,JDBC 就像是一套 Java 访问数据库的 API 规范,利用这套规范屏蔽了各种数据库 API 调用的差异性。当应用程序需要访问数据库时,调用 JDBC API 相关代码进新操作,再由JDBC调用各类数据库的驱动包进行数据操作,最后数据库驱动包和对应的数据库通讯协议完成对应的数据库操作。
在Java领域,数据持久化有几个常见的方案,有Spring Boot自带的JdbcTemplate、有MyBatis,还有JPA,在这些方案中,最简单的就是Spring Boot自带的JdbcTemplate,虽然没有MyBatis功能强大,但是,使用比较简单,事实上,JdbcTemplate应该算是最简单的数据持久化方案。
二、快速开始
开始之前,需要创建一个Spring Boot项目,JdbcTemplate的引用很简单,开发者在创建一个SpringBoot项目时,选上Jdbc以及数据库驱动依赖即可。之前介绍过如何创建项目这里就不介绍,直接使用之前创建的项目工程。
1、依赖配置
1、pom添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
需要注意的是:
如果是用数据库连接池,记得添加Druid数据库连接池依赖。
这里可以添加专门为Spring Boot打造的druid-spring-boot-starter,JdbcTemplate默认使用Hikari 连接池,如果需要使用druid,需要另外配置。
2、application.properties配置数据源
接下来需要在application.properties中提供数据的基本配置即可,如下:
spring.datasource.url=jdbc:mysql://localhost:3306/zwz_test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver
注意:在 Spring Boot 2.1.0 中, com.mysql.jdbc.Driver 已经过期,推荐使用com.mysql.cj.jdbc.Driver
如此之后,所有的配置就算完成了,接下来就可以直接使用JdbcTemplate了,是不是特别方便。其实这就是SpringBoot的自动化配置带来的好处。
2、数据库和实体类
1、数据库表
DROP TABLE IF EXISTS `products`; CREATE TABLE `products` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', `name` varchar(32) DEFAULT NULL COMMENT '名称', `code` varchar(32) DEFAULT NULL COMMENT '编码', `price` int DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2、实体类
package com.weiz.pojo; public class Product { private Long id; private String name; private String code; private int price; public Product(String name, String code, int price) { this.name = name; this.code = code; this.price = price; } // 省略 getter setter }
实体类的数据类型要和数据库字段一一对应,否则会有问题。
3、Serverice封装
创建ProductService和ProductServiceImpl类
1、创建 UserService 定义我们常用的增删改查接口
package com.weiz.service; import com.weiz.pojo.Product; public interface ProductService { int save(Product product); int update(Product product); int delete(long id); Product findById(long id); }
2、创建 ProductServiceImpl 类实现 ProductService 类接口
package com.weiz.service.impl; import com.weiz.pojo.Product; import com.weiz.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @Service public class ProductServiceImpl implements ProductService { @Autowired private JdbcTemplate jdbcTemplate; @Override public int save(Product product) { return jdbcTemplate.update("INSERT INTO products(name, code, price) values(?, ? , ?)", product.getName(), product.getCode(), product.getPrice()); } @Override public int update(Product product) { return jdbcTemplate.update("UPDATE products SET name = ? , code = ? , price = ? WHERE id=?", product.getName(), product.getCode(), product.getPrice(), product.getId()); } @Override public int delete(long id) { return jdbcTemplate.update("DELETE FROM products where id = ? ",id); } @Override public Product findById(long id) { return jdbcTemplate.queryForObject("SELECT * FROM products WHERE id=?", new Object[] { id }, new BeanPropertyRowMapper<Product>(Product.class)); } }
代码说明:
UserServiceImpl类上使用 @Service 注解用于标注数据访问组件,@Autowired 在类中注入 JdbcTemplate,JdbcTemplate是 Spring Boot操作JDBC 提供的工具类 。
除了以上这些基本用法之外,JdbcTemplate也支持其他用法,例如调用存储过程等,这些都比较容易,而且和Jdbc本身都比较相似,这里也就不做介绍了,有兴趣可以留言讨论。
三、调用测试
接下来我们对jdbc操作数据库的功能进行测试。
1、创建ProductController
package com.weiz.controller; import com.weiz.pojo.Product; import com.weiz.service.ProductService; import com.weiz.utils.JSONResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("product") public class ProductController { @Autowired private ProductService productService; @RequestMapping("/save") public JSONResult save() { Product product = new Product(); product.setCode("iphone 11"); product.setName("iphone 11"); product.setPrice(100); productService.save(product); return JSONResult.ok("保存成功"); } @RequestMapping("/update") public JSONResult update() { long pid = 1; Product product = new Product(); product.setCode("iphone 12"); product.setName("iphone 12"); product.setPrice(200); product.setId(pid); productService.update(product); return JSONResult.ok("修改成功"); } @RequestMapping("/delete") public JSONResult delete(long pid) { productService.delete(pid); return JSONResult.ok("删除成功"); } @RequestMapping("/findbyId") public JSONResult findById(long pid) { Product product = productService.findById(pid); return JSONResult.ok(product); } }
2、启动项目,在浏览器分别输入http://localhost:8080/product/findbyId/1 地址,测试产品查询的功能是否正常。
产品数据查询成功,说明使用JdbcTemplate操作数据库实现成功,我们也可以测试其他的接口,验证其他的接口功能是否正常。
四、多数据源的使用
在实际项目中,经常会碰到使用多个数据源的情况, 比如:需要使用多个host、需要使用多种数据库(MySql、Oracle、SqlServer...)。
SpringBoot中,对此都有相应的解决方案,不过一般来说,如果有多数据源的需求,我还是建议首选分布式数据库中间件MyCat。这些都是比较成熟的框架,不需要自己重新写一套。当然如果一些简单的需求,还是可以使用多数据源的。
Spring Boot中,JdbcTemplate、MyBatis以及Jpa都可以配置多数据源。接下来,就在上面的项目的基础上进行改造,给大家介绍JdbcTemplate 如何配置多数据源。
1、配置多数据源
application.properties配置多个数据源:
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/zwz_test spring.datasource.primary.username=root spring.datasource.primary.password=root spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/zwz_test2 spring.datasource.secondary.username=root spring.datasource.secondary.password=root spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
上面的配置文件,添加了两个数据源,一个是 zwz_test 库,铃个是 zwz_test2 库。
注意:之前单个数据源的数据库连接是:spring.datasource.url,这里多个数据源使用的是 spring.datasource.*.jdbc-url,因为JdbcTemplate默认使用Hikari 连接池,而 HikariCP 读取的是 jdbc-url 。
2、配置JDBC初始化
创建DataSourceConfig,在项目启动的时候读取配置文件中的数据库信息,并对 JDBC 初始化。
package com.weiz.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; @Configuration public class DataSourceConfig { @Primary @Bean(name = "primaryDataSource") @Qualifier("primaryDataSource") @ConfigurationProperties(prefix="spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondaryDataSource") @Qualifier("secondaryDataSource") @ConfigurationProperties(prefix="spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } @Bean(name="primaryJdbcTemplate") public JdbcTemplate primaryJdbcTemplate ( @Qualifier("primaryDataSource") DataSource dataSource ) { return new JdbcTemplate(dataSource); } @Bean(name="secondaryJdbcTemplate") public JdbcTemplate secondaryJdbcTemplate( @Qualifier("secondaryDataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
上面的示例,DataSourceConfig类的作用是在项目启动的时候根据特定的前缀加载不同的数据源,再根据构建好的数据源创建不同的 JDBC。
注意事项:使用多个数据源时,需要添加@Primary注解,@Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者。Primary 意味着"主要的",类似与SQL语句中的"primary key",有且只能有一个,否则会报错。
3、修改Serverice封装
需要对 ProductServerice 中的所有方法法进行改造,增加一个传入参数 JdbcTemplate,根据调用方传入的JdbcTemplate 进行操作。
// ProductService 接口 public interface ProductService { int save(Product product, JdbcTemplate jdbcTemplate); // 省略其他方法 } // ProductServiceImpl @Service public class ProductServiceImpl implements ProductService { @Override public int save(Product product,JdbcTemplate jdbcTemplate) { return jdbcTemplate.update("INSERT INTO products(name, code, price) values(?, ? , ?)", product.getName(), product.getCode(), product.getPrice()); } // 省略其他方法 }
4、调用测试
同样,将之前的ProductController 修改如下:
@RestController @RequestMapping("product") public class ProductController { @Autowired private ProductService productService; @Autowired private JdbcTemplate primaryJdbcTemplate; @Autowired private JdbcTemplate secondaryJdbcTemplate; @RequestMapping("/save") public JSONResult save() { Product product = new Product(); product.setCode("iphone 11"); product.setName("iphone 11"); product.setPrice(100); productService.save(product,primaryJdbcTemplate); productService.save(product,secondaryJdbcTemplate); return JSONResult.ok("保存成功"); } // 省略其他方法 }
在浏览器中输入:/save 地址后,查看zwz_test 和 zwz_test2数据库中的products表,都存入一条数据,说明多数据源插入数据成功,其他方方法也是一样的。这样在实际项目中,我们通过传入不同的JdbcTemplate 实例,就可以操作多个数据库。
最后
以上,就把Spring Boot 使用jdbcTemplate 操作数据库介绍完了。同时也介绍了如何配置使用多数据源。在 Spring Boot 项目中 JDBC 操作数据库是不是非常简单。
这个系列课程的完整源码,也会提供给大家。大家关注我的微信公众号(架构师精进),回复:springboot源码。获取这个系列课程的完整源码。
推荐阅读:
SpringBoot从小白到精通(十二)logback日志配置
SpringBoot从小白到精通(十)使用Interceptor拦截器,一学就会!
SpringBoot从小白到精通(九)使用@Async实现异步执行任务
SpringBoot从小白到精通(八)熟悉@EnableScheduling,一秒搞定定时任务
SpringBoot从小白到精通(七)使用Redis实现高速缓存架构
SpringBoot从小白到精通(六)使用Mybatis实现增删改查【附详细步骤】
SpringBoot从小白到精通(五)Thymeleaf的语法及常用标签
SpringBoot从小白到精通(四)Thymeleaf页面模板引擎
SpringBoot从小白到精通(二)如何返回统一的数据格式
SpringBoot从小白到精通(一)如何快速创建SpringBoot项目