SpringBoot学习笔记六:使用JdbcTemplate访问数据库

SpringJDBC框架承担了资源管理和异常处理的工作,将数据访问的样板代码抽象到模板类之中,从而简化了JDBC代码,使我们只需编写从数据库读写数据所必需的代码。
SpringJDBC提供了三个模板类供选择:

  • JdbcTemplate
    最基本的Spring JDBC模板,支持简单的JDBC数据访问功能以及基于索引参数的查询,上层接口为JdbcOperations
    This is the central class in the JDBC core package. It simplifies the use of JDBC and helps to avoid common errors. It executes core JDBC workflow, leaving application code to provide SQL and extract results. This class executes SQL queries or updates, initiating iteration over ResultSets and catching JDBC exceptions and translating them to the generic, more informative exception hierarchy defined in the org.springframework.dao package.
  • NamedParameterJdbcTemplate
    使用该模板类进行查询时可以将值以命名参数的形式绑定到sql中,而不是使用简单的索引参数,上层接口为NamedParameterJdbcOperations
    Template class with a basic set of JDBC operations, allowing the useof named parameters rather than traditional '?' placeholders.
  • SimpleJdbcTemplate
    已废弃

导入依赖

pom.xml 中添加对 JdbcTemplate 的依赖

<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>

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

连接数据库

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

application.yml

spring:
  application:
    name: spring-boot-jdbc
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
    username: root
    password: mysql123
    driver-class-name: com.mysql.jdbc.Driver

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

2018-07-07 15:28:37.925  INFO 2316 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
2018-07-07 15:28:37.932  INFO 2316 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
2018-07-07 15:28:37.978  INFO 2316 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''

具体编码

表结构

创建tb_user

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(64) NOT NULL COMMENT '用户名',
  `password` varchar(64) NOT NULL COMMENT '用户密码',
  `birthday` date DEFAULT NULL COMMENT '用户生日',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- ----------------------------
-- Records of tb_user
-- ----------------------------
BEGIN;
INSERT INTO `tb_user` VALUES (1, 'aaa', '123456', '1994-08-10');
INSERT INTO `tb_user` VALUES (2, 'bbb', '123456', '1996-07-25');
INSERT INTO `tb_user` VALUES (3, 'ccc', '123456', '2000-05-01');
INSERT INTO `tb_user` VALUES (4, 'ddd', '123456', '1997-05-10');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

实体类

package com.example.springbootjdbc.pojo;

import java.util.Date;

public class User {

    /** 用户id */
    private Integer id;

    /** 用户名 */
    private String username;

    /** 用户密码 */
    private String password;

    /** 用户生日 */
    private Date birthday;
    
    // setters and getters ...
}

Dao层

com.example.springbootjdbc.dao.IUserDao

package com.example.springbootjdbc.dao;

import com.example.springbootjdbc.pojo.User;

import java.util.List;

public interface IUserDao {

    int save(User user);

    int delete(Integer id);

    int update(User user);

    User findById(Integer id);

    List<User> findAll();

    List<User> findList(Integer page, Integer pageSize);

}

com.example.springbootjdbc.dao.impl.UserDaoImpl

package com.example.springbootjdbc.dao.impl;

import com.example.springbootjdbc.dao.IUserDao;
import com.example.springbootjdbc.pojo.User;
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 java.util.List;

@Repository
public class UserDaoImpl implements IUserDao {

    private final JdbcTemplate jdbcTemplate;

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

    @Override
    public int save(User user) {
        String sql = "INSERT INTO tb_user(username, password, birthday) VALUES(?, ?, ?)";
        return jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), user.getBirthday());
    }

    @Override
    public int delete(Integer id) {
        String sql = "DELETE FROM tb_user WHERE id = ?";
        return jdbcTemplate.update(sql, id);
    }

    @Override
    public int update(User user) {
        String sql = "UPDATE tb_user u SET u.username = ?, u.password = ?, u.birthday = ? WHERE u.id = ?";
        return jdbcTemplate.update(sql, user.getUsername(), user.getPassword(), user.getBirthday(), user.getId());
    }

    @Override
    public User findById(Integer id) {
        String sql = "SELECT * FROM tb_user WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
    }

    @Override
    public List<User> findAll() {
        String sql = "SELECT * FROM tb_user";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
    }

    @Override
    public List<User> findList(Integer page, Integer pageSize) {
        String sql = "SELECT * FROM tb_user LIMIT ?, ?";
        Integer offset = (page - 1) * pageSize;
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class), offset, pageSize);
    }

}

Service层

com.example.springbootjdbc.service.IUserService

package com.example.springbootjdbc.service;

import com.example.springbootjdbc.pojo.User;

import java.util.List;

public interface IUserService {

    int save(User user);

    int delete(Integer id);

    int update(User user);

    User findById(Integer id);

    List<User> findAll();

    List<User> findList(Integer page, Integer pageSize);

}

com.example.springbootjdbc.service.impl.UserServiceImpl

package com.example.springbootjdbc.service.impl;

import com.example.springbootjdbc.dao.IUserDao;
import com.example.springbootjdbc.pojo.User;
import com.example.springbootjdbc.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements IUserService {

    private final IUserDao userDao;

    @Autowired
    public UserServiceImpl(IUserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public int save(User user) {
        return userDao.save(user);
    }

    @Override
    public int delete(Integer id) {
        return userDao.delete(id);
    }

    @Override
    public int update(User user) {
        return userDao.update(user);
    }

    @Override
    public User findById(Integer id) {
        return userDao.findById(id);
    }

    @Override
    public List<User> findAll() {
        return userDao.findAll();
    }

    @Override
    public List<User> findList(Integer page, Integer pageSize) {
        return userDao.findList(page, pageSize);
    }
}

Rest 接口

package com.example.springbootjdbc.controller;

import com.example.springbootjdbc.pojo.User;
import com.example.springbootjdbc.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;

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

    private final IUserService userService;

    @Autowired
    public UserController(IUserService userService) {
        this.userService = userService;
    }

    @PostMapping("")
    public String saveUser(@RequestBody User user) {
        int count = userService.save(user);
        return count > 0 ? "success" : "fail";
    }

    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Integer id) {
        int count = userService.delete(id);
        return count > 0 ? "success" : "fail";
    }

    @PutMapping("/{id}")
    public String updateUser(@PathVariable Integer id, @RequestParam(value = "username", required = true) String username,
                          @RequestParam(value = "password", required = true) String password,
                          @RequestParam(value = "birthday", required = true) String birthday) throws ParseException {
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setUsername(username);
        updateUser.setPassword(password);
        updateUser.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse(birthday));
        int count = userService.update(updateUser);
        return count > 0 ? "success" : "fail";
    }

    @GetMapping("")
    public List<User> findList(@RequestParam(value = "page", defaultValue = "1") Integer page,
                               @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        return userService.findList(page, pageSize);
    }

    @GetMapping("{id}")
    public User findById(@PathVariable Integer id) {
        return userService.findById(id);
    }

}


JdbcTemplate API文档

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,656评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,810评论 6 342
  • 2018年3月28日 周三 天气晴p68 今天这天气穿衬衣,明天又得换上毛衣了。下午接...
    童心_依旧阅读 195评论 0 0
  • 一路走过 有阵回声缭绕 不知道是什么存在勾起了记忆 或许是风吧 毕竟是飘过的曲调 路过之后 总感觉有一种滋味 吹拂...
    醉酒的灵魂阅读 138评论 0 0
  • 《茶之书》| 小曼解读 《茶之书》| 小曼解读 关于作者 冈仓天心,是日本明治时期著名的美术活动家、美术教育家、文...
    鸭梨山大哎阅读 877评论 0 1