一起来学 SpringBoot 2.x | 第五篇:使用 JdbcTemplate 访问数据库

点击上方“芋道源码”,选择“置顶公众号”

技术文章第一时间送达!

源码精品专栏

 

摘要: 原创出处 http://blog.battcn.com/2018/05/07/springboot/v2-orm-jdbc/ 「唐亚峰」欢迎转载,保留摘要,谢谢!

  • 导入依赖

  • 连接数据库

  • 具体编码

  • 表结构

  • 实体类

  • restful 风格接口

  • 测试

  • 总结

  • 说点什么


SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程

Spring Framework对数据库的操作在JDBC上面做了深层次的封装,通过依赖注入功能,可以将 DataSource 注册到JdbcTemplate之中,使我们可以轻易的完成对象关系映射,并有助于规避常见的错误,在SpringBoot中我们可以很轻松的使用它。

特点

  • 速度快,对比其它的ORM框架而言,JDBC的方式无异于是最快的

  • 配置简单,Spring自家出品,几乎没有额外配置

  • 学习成本低,毕竟JDBC是基础知识,JdbcTemplate更像是一个DBUtils

导入依赖

在 pom.xml 中添加对 JdbcTemplate 的依赖

<!-- Spring JDBC 的依赖包,使用 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 将会自动获得HikariCP依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MYSQL包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 默认就内嵌了Tomcat 容器,如需要更换容器也极其简单-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

连接数据库

application.properties中添加如下配置。值得注意的是,SpringBoot默认会自动配置DataSource,它将优先采用HikariCP连接池,如果没有该依赖的情况则选取tomcat-jdbc,如果前两者都不可用最后选取Commons DBCP2通过spring.datasource.type属性可以指定其它种类的连接池

spring.datasource.url=jdbc:mysql://localhost:3306/chapter4?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.password=root
spring.datasource.username=root
#spring.datasource.type
#更多细微的配置可以通过下列前缀进行调整
#spring.datasource.hikari
#spring.datasource.tomcat
#spring.datasource.dbcp2

启动项目,通过日志,可以看到默认情况下注入的是HikariDataSource

2018-05-07 10:33:54.021  INFO 9640 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-05-07 10:33:54.026  INFO 9640 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-05-07 10:33:54.071  INFO 9640 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-05-07 10:33:54.075  INFO 9640 --- [           main] com.battcn.Chapter4Application           : Started Chapter4Application in 3.402 seconds (JVM running for 3.93)

具体编码

完成基本配置后,接下来进行具体的编码操作。为了减少代码量,就不写UserDao、UserService之类的接口了,将直接在Controller中使用JdbcTemplate进行访问数据库操作,这点是不规范的,各位别学我…

表结构

创建一张 t_user 的表

CREATE TABLE `t_user` (
  `id` int(8NOT NULL AUTO_INCREMENT COMMENT '主键自增',
  `username` varchar(50NOT NULL COMMENT '用户名',
  `password` varchar(50NOT NULL COMMENT '密码',
  PRIMARY KEY (`id`)
ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

实体类

package com.battcn.entity;

/**
 * @author Levin
 * @since 2018/5/7 0007
 */

public class User {

    private Long id;
    private String username;
    private String password;
    // TODO  省略get set
}

restful 风格接口

package com.battcn.controller;

import com.battcn.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author Levin
 * @since 2018/4/23 0023
 */

@RestController
@RequestMapping("/users")
public class SpringJdbcController {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public SpringJdbcController(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @GetMapping
    public List<User> queryUsers() {
        // 查询所有用户
        String sql = "select * from t_user";
        return jdbcTemplate.query(sql, new Object[]{}, new BeanPropertyRowMapper<>(User.class));
    }

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // 根据主键ID查询
        String sql = "select * from t_user where id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper<>(User.class));
    }

    @DeleteMapping("/{id}")
    public int delUser(@PathVariable Long id) {
        // 根据主键ID删除用户信息
        String sql = "DELETE FROM t_user WHERE id = ?";
        return jdbcTemplate.update(sql, id);
    }

    @PostMapping
    public int addUser(@RequestBody User user) {
        // 添加用户
        String sql = "insert into t_user(username, password) values(?, ?)";
        return jdbcTemplate.update(sql, user.getUsername(), user.getPassword());
    }


    @PutMapping("/{id}")
    public int editUser(@PathVariable Long id, @RequestBody User user) {
        // 根据主键ID修改用户信息
        String sql = "UPDATE t_user SET username = ? ,password = ? WHERE id = ?";
        return jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), id);
    }
}

测试

由于上面的接口是 restful 风格的接口,添加和修改无法通过浏览器完成,所以需要我们自己编写junit或者使用postman之类的工具。

创建单元测试Chapter4ApplicationTests,通过TestRestTemplate模拟GET、POST、PUT、DELETE等请求操作

package com.battcn;

import com.battcn.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

/**
 * @author Levin
 */

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Chapter4Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Chapter4ApplicationTests {

    private static final Logger log = LoggerFactory.getLogger(Chapter4ApplicationTests.class);
    @Autowired
    private TestRestTemplate template;
    @LocalServerPort
    private int port;

    @Test
    public void test1() throws Exception {
        template.postForEntity("http://localhost:" + port + "/users"new User("user1""pass1"), Integer.class);
        log.info("[添加用户成功]\n");
        // TODO 如果是返回的集合,要用 exchange 而不是 getForEntity ,后者需要自己强转类型
        ResponseEntity<List<User>> response2 = template.exchange("http://localhost:" + port + "/users", HttpMethod.GET, nullnew ParameterizedTypeReference<List<User>>() {
        });
        final List<User> body = response2.getBody();
        log.info("[查询所有] - [{}]\n", body);
        Long userId = body.get(0).getId();
        ResponseEntity<User> response3 = template.getForEntity("http://localhost:" + port + "/users/{id}", User.class, userId);
        log.info("[主键查询] - [{}]\n", response3.getBody());
        template.put("http://localhost:" + port + "/users/{id}"new User("user11""pass11"), userId);
        log.info("[修改用户成功]\n");
        template.delete("http://localhost:" + port + "/users/{id}", userId);
        log.info("[删除用户成功]");
    }
}

总结

本章介绍了JdbcTemplate常用的几种操作,详细请参考JdbcTemplate API文档

目前很多大佬都写过关于 SpringBoot 的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE编写,包括新版本的特性都会一起介绍…

说点什么

全文代码:https://github.com/battcn/spring-boot2-learning/tree/master/chapter4

666. 彩蛋




如果你对 Dubbo 感兴趣,欢迎加入我的知识星球一起交流。

640?

知识星球



目前在知识星球(https://t.zsxq.com/2VbiaEu)更新了如下 Dubbo 源码解析如下:

01. 调试环境搭建
02. 项目结构一览
03. 配置 Configuration
04. 核心流程一览

05. 拓展机制 SPI

06. 线程池

07. 服务暴露 Export

08. 服务引用 Refer

09. 注册中心 Registry

10. 动态编译 Compile

11. 动态代理 Proxy

12. 服务调用 Invoke

13. 调用特性 

14. 过滤器 Filter

15. NIO 服务器

16. P2P 服务器

17. HTTP 服务器

18. 序列化 Serialization

19. 集群容错 Cluster

20. 优雅停机

21. 日志适配

22. 状态检查

23. 监控中心 Monitor

24. 管理中心 Admin

25. 运维命令 QOS

26. 链路追踪 Tracing

...
一共 60 篇++


源码不易↓↓↓

点赞支持老艿艿↓↓

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值