Spring Boot 快速入门系列(III)—— 数据操作篇之 JdbcTemplate

本文基于《Spring Boot 快速入门系列》,演示通过 Spring JdbcTemplate 完成基础数据库 CRUD 操作。介绍了引入依赖、建表、创建实体类等步骤,还展示了 dao、service、controller 层代码及页面文件,最后重启项目进行演示,下一篇将介绍 Mybatis。

1. 前言

从《Spring Boot 快速入门系列》第三篇中(Spring Boot 快速入门系列(II)—— 数据操作篇之 Spring Data JPA),我们已经学习和了解如何通过Spring Data JPA 完成基础的数据库(CRUD)持久化操作,今天我们就来演示另一种数据库持久化操作的方式,即通过 Spring JdbcTemplate 完成基础的数据库 CRUD 操作。

 

2. Spring JdbcTemplate 使用演示

在这之前我们先回顾一下JDBC操作数据库的步骤及编码吧!

# 步骤大概如下:
1)加载数据库驱动(到JVM);
2)建立数据库连接;
3)创建数据库操作对象;
4)定义操作的SQL语句;
5)执行数据库操作;
6)获取并操作结果集;
7)关闭对象,回收数据库资源。
package cn.giserway.helloworld.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

@Test 
public class JDBCTest {
  /**
   * 使用JDBC连接并操作mysql数据库
   */
  public static void main(String[] args) {
    // mysql数据库驱动类名
    String driver = "com.mysql.jdbc.Driver";
    // 数据库连接地址
    String url = "jdbc:mysql://localhost:3306/db_test";
    // 用户名
    String username = "root";
    // 密码
    String password = "123456";
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    try {
      // 1、加载数据库驱动
      Class.forName(driver);
      // 2、获取数据库连接
      conn = DriverManager.getConnection(url, username, password);
      // 3、获取数据库操作对象
      stmt = conn.createStatement();
      // 4、定义操作的SQL语句
      String sql = "select * from t_game";
      // 5、执行数据库操作
      rs = stmt.executeQuery(sql);
      // 6、获取并操作结果集
      while (rs.next()) {
        System.out.println(rs.getInt("id"));
        System.out.println(rs.getString("name"));
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      // 7、关闭对象,回收数据库资源
      if (rs != null) { //关闭结果集对象
        try {
          rs.close();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
      if (stmt != null) { // 关闭数据库操作对象
        try {
          stmt.close();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
      if (conn != null) { // 关闭数据库连接对象
        try {
          if (!conn.isClosed()) {
            conn.close();
          }
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
从上面的JDBC实现来看,简单的查询数据库获取结果集代码就非常冗余(但是作为初学者你必须得会,不管什么数据库持久化框架,都是对JDBC操作的封装),最后还需要手动关闭资源及捕获各种异常。等你学会了 JDBC模板操作数据库就简单多了,废话不多说,开撸……

下面通过一个简单的图书管理页面演示 Spring Boot 下 Spring JdbcTemplate 操作数据库的基本方法。

1)紧接着上一篇项目工程继续,通过 Maven 项目的 pom.xml 文件引入  Spring JdbcTemplate 数据持久化操作依赖的Jar 包,具体的引入方式如下:

<!-- Spring JdbcTemplate -->
<dependency>    
    <groupId>org.springframework.boot</groupId>    
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

2)在数据库 db_test 中新增 t_book 图书信息表,sql 语句如下:

create table t_book (
  id int(11) not null auto_increment,
  book_name varchar(20) not null,
  money double default null,
  primary key (id)
) engine=innodb default charset=utf8;

insert into t_book values (null, '九阳神功', '100');
insert into t_book values (null, '独孤九剑', '200');
insert into t_book values (null, '如来神掌', '300');

3)在 domain 包下新建对应的 Book 实体类,代码如下:

package cn.giserway.helloworld.domain;

/**
 * @program: helloworld
 * @author: giserway
 **/
public class Book {
    private Integer id;
    private String bookName;   
    private double money;
    // 省略 set/get 方法 ...
    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", bookName='" + bookName + '\'' +
                ", money=" + money +
                '}';
    }
}

4)下面我们开始使用 Spring JDBC模板来实现数据库的 CRUD 持久化操作,视图层采用 Freemarker 模板实现。

JdbcTemplate 持久化相关代码实现如下:

dao 层

在 dao 包下创建接口 IBookDao,代码如下:

package cn.giserway.helloworld.dao;

import cn.giserway.helloworld.domain.Book;
import java.util.List;

/**
 * @program: helloworld
 * @author: giserway
 **/
public interface IBookDao {
    /**
     * 查询所有图书
     */
    List<Book> findAll();
    /**
     * 通过id查询图书
     * @param id
     * @return
     */
    Book findById(Integer id);
    /**
     * 新增图书
     * @param book
     * @return
     */
    int add(Book book);
    /**
     * 更新图书
     * @param book
     * @return
     */
    int update(Book book);
    /**
     * 通过id删除图书
     * @param id
     * @return
     */
    int deleteById(Integer id);
}

在 daoImpl 包下新建 bookDaoImpl 实现 IBookDao 接口,代码如下:

package cn.giserway.helloworld.dao.daoImpl;

import cn.giserway.helloworld.dao.IBookDao;
import cn.giserway.helloworld.domain.Book;
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;

/**
 * @program: helloworld
 * @author: giserway
 **/
@Repository
public class BookDaoImpl implements IBookDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public List<Book> findAll() {
        List<Book> list = jdbcTemplate.query("select * from t_book", new Object[]{}, new BeanPropertyRowMapper<>(Book.class));
        if (!list.isEmpty()) {
            return list;
        }
        return null;
    }
    @Override
    public Book findById(Integer id) {
        return jdbcTemplate.queryForObject("select * from t_book where id = ?", new Object[]{ id }, new BeanPropertyRowMapper<>(Book.class));
    }
    @Override
    public int add(Book book) {
        return jdbcTemplate.update("insert into t_book(id, book_name, money) values(null, ?, ?)", book.getBookName(), book.getMoney());
    }
    @Override
    public int update(Book book) {
        return jdbcTemplate.update("update t_book set book_name = ?, money = ? where id = ?", book.getBookName(), book.getMoney(), book.getId());
    }
    @Override
    public int deleteById(Integer id) {
        return jdbcTemplate.update("delete from t_book where id = ?", id);
    }
}

service 层

在 service 包下新建接口 IBookService,代码如下:

package cn.giserway.helloworld.service;

import cn.giserway.helloworld.domain.Book;
import java.util.List;

/**
 * @program: helloworld
 * @author: giserway
 **/
public interface IBookService {
    /**
     * 查询所有图书
     */
    List<Book> findAll();

    /**
     * 通过id查询图书
     * @param id
     * @return
     */
    Book findById(Integer id);

    /**
     * 新增图书
     * @param book
     * @return
     */
    int add(Book book);

    /**
     * 更新图书
     * @param book
     * @return
     */
    int update(Book book);

    /**
     * 通过id删除图书
     * @param id
     * @return
     */
    int deleteById(Integer id);
}

在 serviceImpl 包下实现 IBookService 接口,代码如下:

package cn.giserway.helloworld.service.serviceImpl;

import cn.giserway.helloworld.dao.IBookDao;
import cn.giserway.helloworld.domain.Book;
import cn.giserway.helloworld.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

/**
 * @program: helloworld
 * @author: giserway
 **/
@Service
public class bookServiceImpl implements IBookService {
    @Autowired
    IBookDao bookDao;
    @Override
    public List<Book> findAll() {
        return bookDao.findAll();
    }
    @Override
    public Book findById(Integer id) {
        return bookDao.findById(id);
    }
    @Override
    public int add(Book book) {
        return bookDao.add(book);
    }
    @Override
    public int update(Book book) {
        return bookDao.update(book);
    }
    @Override
    public int deleteById(Integer id) {
        return bookDao.deleteById(id);
    }
}

controller 层

在 controller 包下创建 BookController 类,代码如下:

package cn.giserway.helloworld.controller;

import cn.giserway.helloworld.domain.Book;
import cn.giserway.helloworld.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 * @program: helloworld
 * @author: giserway
 **/
@Controller
@RequestMapping("/book")
public class BookController {
    @Autowired
    IBookService bookService;

    /**
     * 查询所有图书
     * @return
     */
    @RequestMapping(value="/list")
    public ModelAndView list(){
        ModelAndView mav = new ModelAndView();
        mav.addObject("bookList", bookService.findAll());
        mav.setViewName("bookList");
        return mav;
    }

    /**
     * 添加图书
     * @param book
     * @return
     */
    @RequestMapping(value="/add",method=RequestMethod.POST)
    public String add(Book book){
        bookService.add(book);
        return "forward:/book/list";
    }

    /**
     * 跳转修改页面
     * @param id
     * @return
     */
    @GetMapping(value="/preUpdate/{id}")
    public ModelAndView preUpdate(@PathVariable("id") Integer id){
        ModelAndView mav = new ModelAndView();
        mav.addObject("book", bookService.findById(id));
        mav.setViewName("bookUpdate");
        return mav;
    }

    /**
     * 更新图书
     * @param book
     * @return
     */
    @PostMapping(value="/update")
    public String update(Book book){
        bookService.update(book);
        return "forward:/book/list";
    }

    /**
     * 删除图书
     * @param id
     * @return
     */
    @RequestMapping(value="/delete",method= RequestMethod.GET)
    public String delete(Integer id){
        bookService.deleteById(id);
        return "forward:/book/list";
    }
}

5)在 templates (模板文件存放位置)文件夹(src/main/resources/templates)下新建一个 bookList.ftl(图书列表)、bookUpdate.ftl (图书更新),在 static (静态页面存放位置)文件夹下新建 bookAdd.html(图书添加)文件。

文件结构如下:

页面代码如下所示:

bookList.ftl

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>图书管理系统</title>
</head>
<body>
<a href="/bookAdd.html">添加图书</a>
<table>
    <tr>
        <th>编号</th>
        <th>图书名称</th>
        <th>图书价格</th>
        <th>操作</th>
    </tr>
    <#list bookList as book>
    <tr>
        <td>${book.id}</td>
        <td>${book.bookName}</td>
        <td>${book.money}</td>
        <td>
            <a href="/book/preUpdate/${book.id}">修改</a>
            <a href="/book/delete?id=${book.id}">删除</a>
        </td>
    </tr>
    </#list>
</table>
</body>
</html>

注:需在 application.yml 文件中添加如下配置解决 bookList.ftl 文件中<#list bookList as book> 的 bookList 不为空的bug

spring:
  freemarker:
    settings:
      classic_compatible: true

bookUpdate.ftl 

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>图书更新页面</title>
</head>
<body>
<form action="/book/update" method="post">
    <input type="hidden" name="id" value="${book.id}"/>
    图书名称:<input type="text" name="bookName" value="${book.bookName}"/><br/>
    图书价格:<input type="text" name="money" value="${book.money}"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

bookAdd.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>图书添加页面</title>
</head>
<body>
<form action="book/add" method="post">
    图书名称:<input type="text" name="bookName"/><br/>
    图书价格:<input type="text" name="money"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

6)重新启动 Spring Boot 项目,JdbcTemplate 持久化演示动图如下:

浏览器输入:http://localhost:9999/book/list

 

3. 小结

今天我们通过 Spring JdbcTemplate 学会了简单的数据库的持久化操作。开发人员通过项目的 pom.xml 文件添加相关依赖的Jar,在 dao 层注入JdbcTemplate 模板即可使用,就是这么简单!还不快试一试哈……

下一篇文章我们将会演示 Spring Boot 快速入门系列(IV)—— 数据操作篇之 Mybatis。

 

 

# 精彩推荐 #

Spring Boot 快速入门系列(先导篇) —— 从 Hello World 开始

Spring Boot 快速入门系列(I) —— 属性配置篇

Spring Boot 快速入门系列(II)—— 数据操作篇之 Spring Data JPA

分布式事务了解吗?你们是如何解决分布式事务问题的?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值