5.1 Spring Boot集成JdbcTemplate

原生的jdbc操作并不友好:需要自己加载驱动、创建连接、写数据库查询/薪资/修改/删除的SQL(或调用存储过程)、自己控制事务、完成从数据库返回的ResultSet(java.sql.ResultSet)中取数(字段值)并且再把这些数存放到对象中。整个过程比较复杂,经常重复,并且没有什么技术含量。

针对这种情况,各种ORM( Object Relational Mapping, 对象关系映射)技术应运而生,解决关系数据库到java对象的匹配问题。在这个领域中,经常使用到的有JPA、Hibernate、MyBatis等ORM框架。

当然,在大部分项目情况下,我们都会直接使用更加强大的持久化框架来访问数据库,比如MyBatis、Hibernate或者Spring Data JPA,但有的时候在项目中也会直接用到原生jdbc来操作数据库。我现在能够想到的唯一原因,就是原生jdbc直接、小巧、不引入第三方库。

但是,在Spring应用中,直接使用jdbc方式已经几乎见不到了。为了方便,Spring对数据库的操作在jdbc上面做了更深层次的封装(也是非常薄的一层封装)。

Spring封装提供的JdbcTemplate就是一个操作数据库的便捷工具。我们可以借助JdbcTemplate来执行所有数据库操作,例如插入,更新,删除和从数据库中检索数据,并且有效避免直接使用jdbc带来的繁琐编码。

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

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句。
  • update、batchUpdate方法:用于执行新增、修改、删除等语句。
  • query方法及queryForXXX方法:用于执行查询相关的语句。
  • call方法:用于执行数据库存储过程和函数相关的语句。

下面我们在Spring Boot应用中引入JdbcTemplate方式操作数据,看看如何将JdbcTemplate技术集成到Spring Boot中去。

5.1.1 新建项目

使用Spring Starter工具新建Spring Boot项目。

注意要选中JDBC API、MySQL Driver和Spring Web的依赖。

JDBC API依赖对应的starter是:spring-boot-starter-jdbc

image-20191115234354265

项目的pom文件,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>jdbc-template</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jdbc-template</name>
    <description>JdbcTemplate Example.</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

项目的配置文件application.yml中配置数据库连接信息。

# mysql数据源配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/spring_boot_course?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

需要注意的是:在我们的练习环境中使用的是MySQL 5.7数据库,Spring Boot使用当前的jdbc驱动(8.0.18)application.yml配置需要注意如下两点:

  • url需要设置时区参数,例如jdbc:mysql://localhost:3306/spring_boot_course?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
  • jdbc驱动,需要使用com.mysql.cj.jdbc.Driver

5.1.2 新建Entity类

实体类,一般对应了数据库中的表,其中的每一个属性,对应了表中的一个字段。

package com.example.jdbctemplate.entity;

public class User {

    private Integer id;
    private String userName;
    private String passWord;
    private String realName;
(省略getter、setter)
    @Override
    public String toString() {

        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", realName='" + realName + '\'' +
                '}';
    }
}

对应表user的MySQL DDL如下:

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(32) NOT NULL AUTO_INCREMENT,
  `userName` varchar(32) NOT NULL,
  `passWord` varchar(50) NOT NULL,
  `realName` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

插入1条数据,供测试:

INSERT INTO `user` VALUES ('1', 'Kevin', '123456', '长的帅');

5.1.3 新建DAO类

DAO类是通过JdbcTemplate存取数据的关键,并且通过@Repository注解将其纳入Spring容器管理,供其他Spring组件(bean)使用,一般都是注入到Service类中。

package com.example.jdbctemplate.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.example.jdbctemplate.entity.User;

@Repository
public class UserDAO {

    @Autowired
    JdbcTemplate jdbcTemplate;

    public User getUser(int id) {
        String sql = "select * from user where id=" + id;
        return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class));
    }

}

注意上面代码中的第13-14行,其中直接注入了JdbcTemplate对象,供操作SQL用。

第17-18行,就是使用JdbcTemplate对象完成了一次查询,并且将数据库查询结果(一行数据)封装(BeanPropertyRowMapper)到了一个对象(实体类User对象)中。

JdbcTemplate对象是从哪里来的?那就是Spring Boot Starter(启动器)的魔法了。

在本项目中,spring-boot-starter-jdbc自动在Spring容器中注册了JdbcTemplate对象。

5.1.4 新建Service类

服务类中注入DAO类,在向外提供的服务中需要用数据库操作时,调用DAO对象的对应方法,即可和数据库交互。

package com.example.jdbctemplate.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.jdbctemplate.dao.UserDAO;
import com.example.jdbctemplate.entity.User;

@Service
public class UserService {

    @Autowired
    UserDAO userDAO;

    public User getUser(int id) {
        return userDAO.getUser(id);
    }

}

5.1.5 新建Controller类

新建一个控制器类,在接收到用户请求/user/get/1时通过Service对象中的DAO对象对应方法访问数据库中id=1的这条记录,并通过ResponseBody返回。

package com.example.jdbctemplate.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.jdbctemplate.service.UserService;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("get/{id}")
    public String getUser(@PathVariable int id) {
        return userService.getUser(id).toString();
    }

}

5.2.6 运行验证

运行该项目的启动类JdbcTemplateApplication,在浏览器中访问http://localhost:8080/user/get/1,验证是否可以正确的查询到数据库中的记录。

image-20191114105653938

以上就是如何在Spring Boot中集成JdbcTemplate,使用最简单最原始的SQL与数据库交互的示例。

在大多数情况下,我们都会选择一些ORM技术来与数据库进行交互,下一小节,我们会介绍MyBatis这个ORM框架。

本小节示例项目代码:

https://github.com/gyzhang/SpringBootCourseCode/tree/master/spring-boot-jdbc

results matching ""

    No results matching ""