JDBCTemplate相对于其他ORM框架来说是极其简单和极容易上手的一个数据库连接的封装。在学习JDBCTemplate之前,我们先来了解一下JDBC相关的概念和操作。

JDBC简介

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。它由一组用Java语言编写的类和接口组成。通常说的JDBC是面向关系型数据库的。

通过下图,我们将了解JDBC在整个系统中的位置。

Spring Boot集成JDBCTemplate_java

在整个系统中,java应用程序通过JDBC提供的API连接到JDBC Driver,而这些JDBC驱动器的具体实现是由各大数据库厂家针对JDBC规范而编写,并提供给使用者。

使用JDBC时的实例代码如下:

 

public class DbUtil {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/spring"; private static final String USER = "root"; private static final String PASSWORD = "123_123";
public static void main(String[] args) {
Connection conn = null; try { //1.加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); //2. 建立数据库连接 conn = DriverManager.getConnection(URL, USER, PASSWORD); //3.创建数据库操作对象,实现增删改查 Statement stmt = conn.createStatement(); //4.定义操作的SQL语句 //5.执行数据库操作 ResultSet rs = stmt.executeQuery("SELECT order_no, amount FROM tb_order"); //6.获取并操作结果集 while (rs.next()) { System.out.println("订单号:" + rs.getString("order_no") + " 金额:" + rs.getInt("amount")); } } catch (Exception e) { // 日志信息 } finally { // 7、关闭资源 if (conn != null) { try { conn.close(); } catch (SQLException e1) { e1.printStackTrace(); } } } }}

通过上述操作,我们会发现整个操作步骤非常复杂,而且涉及到数据库驱动加载、建立链接、执行操作、解析结果、资源的关闭、异常处理等多个步骤。

JDBCTemplate

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

JdbcTemplate全限定命名为org.springframework.jdbc.core.JdbcTemplate。

JdbcTemplate主要方法

JdbcTemplate主要提供以下五类方法:

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

  • update方法及batchUpdate方法。update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;

  • query方法及queryForXXX方法,用于执行查询相关语句;

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

Spring Boot集成

添加依赖

首先添加依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

其中spring-boot-starter-jdbc引入spring jdbc相关依赖,mysql-connector-java引入关于mysql连接相关实现的jar包。

在IDE中点击spring-boot-starter-jdbc,会导航到该starter的依赖,在其中我们可以下面的依赖:

<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
<scope>compile</scope>
</dependency>

其中spring-jdbc是spring为jdbc提供的工具包,而HikariCP是数据库连接池。号称是“世界上最快”的连接池。

实体类

针对数据库表结构,我们创建如下实体类(使用了Lombok):

@Data
public class Order {

private int id;

private String orderNo;

private int amount;
}

配置数据库连接池

在application.properties中配置数据库连接池

spring.datasource.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123_123
# Spring Boot 2.1.0 中,com.mysql.jdbc.Driver 已经过期
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

其中注意不同版本推荐的驱动类。

使用JDBCTemplate

经过以上步骤,我们就可以在Service层或DAO层(根据系统情况调整)中使用JDBCTemplate。

这里OrderService接口定义如下:

package com.secbro.service;

import com.secbro.model.Order;

import java.util.List;

/**
* @author sec
* @version 1.0
* @date 2020/2/29 8:58 AM
**/
public interface OrderService {

/**
* 创建订单
* @param order 订单信息
* @return 记录数
*/
int save(Order order);


/**
* 更新订单
* @param order 订单信息
* @return 记录数
*/
int update(Order order);


/**
* 删除
* @param id id
* @return 条数
*/
int delete(int id);

/**
* 根据ID查询
* @param id 订单id
* @return 订单详情
*/
Order findById(int id);

/**
* 查询所有
* @return 列表
*/
List<Order> findAll();
}

接口的具体实现如下:

package com.secbro.service.impl;

import com.secbro.model.Order;
import com.secbro.service.OrderService;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
* @author sec
* @version 1.0
* @date 2020/2/29 8:58 AM
**/
@Service("orderService")
public class OrderServiceImpl implements OrderService {

@Resource
private JdbcTemplate jdbcTemplate;

@Override
public int save(Order order) {
return jdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),
order.getAmount());
}

@Override
public int update(Order order) {
return jdbcTemplate.update("update tb_order set amount = ? where id = ?", order.getAmount(), order.getId());
}

@Override
public int delete(int id) {
return jdbcTemplate.update("delete from tb_order where id = ?", id);
}

@Override
public Order findById(int id) {
return jdbcTemplate.queryForObject("select * from tb_order where id = ?", new Object[]{id},
new BeanPropertyRowMapper<>(Order.class));
}

@Override
public List<Order> findAll() {
return jdbcTemplate.query("select * from tb_order", new OrderRowMapper());
}

/**
* RowMapper 可以将数据中的每一行数据封装成用户定义的类,实现RowMapper接口的mapRow方法
*/
class OrderRowMapper implements RowMapper<Order> {

@Override
public Order mapRow(ResultSet rs, int rowNum) throws SQLException {
// 对数据的返回处理
Order order = new Order();
order.setId(rs.getInt("id"));
order.setOrderNo(rs.getString("order_no"));
order.setAmount(rs.getInt("amount"));
return order;
}
}
}

可以看到,直接使用@Resource将JdbcTemplate注入对应的类中便可以使用了。

单元测试

相关的单元测试方法,如下(基于Junit5):

package com.secbro.service;

import com.secbro.model.Order;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.List;

/**
* @author zzs
*/
@Slf4j
@SpringBootTest
class OrderServiceTest {

@Resource
private OrderService orderService;

@Test
void save() {
Order order = new Order();
order.setOrderNo("N003");
order.setAmount(10000);
orderService.save(order);
}

@Test
void update() {
Order order = new Order();
order.setId(1);
order.setOrderNo("N001");
order.setAmount(8888);
orderService.update(order);
}

@Test
void delete() {
orderService.delete(2);
}

@Test
void findById() {
Order order = orderService.findById(3);
log.info("订单信息:{}", order);
}

@Test
void findAll() {
List<Order> list = orderService.findAll();
log.info("所有订单信息:{}", list);
}
}

小结

至此,关于Spring Boot集成JDBCTemplate的基本操作完成,关于集成中可能会发生的错误和源代码分析。我们将在下一篇文章中进行讲解。