
图源:
上篇文章介绍了如何接收和处理HTTP请求,这篇文章将介绍如何连接数据库,并通过数据库来存储和读取数据。
准备工作
在介绍使用Spring Boot框架使用数据库前,需要先有一个数据库才行,这里推荐使用MySQL。其安装方式是多种多样的,我是通过XAMPP安装的,相关内容可以阅读。
还推荐安装一个数据库客户端,这样操作和查看数据库更方便,对于MySQL,我一直使用的是SQLyog。可以通过下边的连接下载安装一个:
下面示例会使用一个user表,这里给出DDL语句:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(10) NOT NULL COMMENT '姓名',
`age` int(11) NOT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
数据库名称我使用的是test。
下面我们将一步步在上篇文章那个简单Web应用的基础上添加上对数据库的支持。
可以从获取上篇文章的Web应用示例代码。
数据库配置
首先我们需要在Maven配置中添加对JDBC和MySQL的支持。其中JDBC是一个在数据库驱动之上的抽象层,Java可以通过JDBC来统一地访问各种类型的数据库。因此无论是使用何种数据库,都应当添加对JDBC的支持。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
MySQL 驱动的依赖包似乎已经修改了 maven 仓库的名称,如果使用上边的依赖出错,可以尝试下边新的maven 依赖:
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency>
Spring Boot的配置文件application.properties中添加数据库IP、帐号密码等相关信息:
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
我这里的密码是空,因为本地测试库没有设置密码。
Service
为了让代码更灵活,这里我们需要在实体层和Controller之间创建一个“中间层”Service,用于对Controller提供基础的数据读写功能。
一些结构简单的语言,如PHP,其实会将
Service层的代码写入Model层。
下面是UserService的完整代码:
package cn.icexmoon.my_first_app.service;
import cn.icexmoon.my_first_app.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
public class UserService {
JdbcTemplate jdbcTemplate;
public long addUser(User user){
String sql = "INSERT INTO `user` (`name`, `age`) VALUES (?, ?)";
PreparedStatementCreator preparedStatementCreator = new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1,user.getName());
ps.setInt(2, user.getAge());
return ps;
}
};
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(preparedStatementCreator, keyHolder);
return keyHolder.getKey().longValue();
}
public void deleteUser(long id) {
jdbcTemplate.update("delete from user where id=?", id);
}
public List<User> getUsers() {
List<User> users = jdbcTemplate.query("SELECT `id`,`name`,`age` FROM USER", new BeanPropertyRowMapper<>(User.class));
return users;
}
public User getUser(long id) {
String sql = String.format("select `id`,`name`,`age` from user where id=%d",id);
User user;
try{
user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class));
}
catch (EmptyResultDataAccessException e){
return null;
}
return user;
}
public void updateUser(User user){
String sql = String.format("UPDATE `user` SET`name`='%s',`age`='%d' WHERE id=%d",user.getName(),user.getAge(),user.getId());
jdbcTemplate.update(sql);
}
}
Spring Boot的Service层类使用@Service注解。这里使用了一个基础的JDBC连接类JdbcTemplate,它可以提供基础的数据库操作。
Spring Boot最优秀的地方在于,我们不需要编写数据库连接和断开的相关处理代码,只需要为JdbcTemplate添加一个@Autowired注解,框架就会对其正确初始化,并在需要时连接数据库,在不需要时断开数据库。
JdbcTemplate提供这么几种基本方法对数据库进行操作:
-
JdbcTemplate.update,执行数据变更SQL,如update、delete等。 -
JdbcTemplate.query,执行数据查询SQL,即select。 -
JdbcTemplate.exec,执行DDL语句,如create table。
具体的实现这里就不细说了,比较简单,看示例即可。值得一说的有:
-
为了实现添加数据后返回自增主键,这里使用了一个
PreparedStatementCreator匿名类,并用它返回一个可以处理SQL语句的PreparedStatement对象。最后再使用一个KeyHolder对象来保存生成的自增主键值。 -
queryForObject可以查询单条数据,并以实体类的方式返回,但在查询不到结果时会抛出一个EmptyResultDataAccessException异常,这里对其进行捕获,并返回null。
Controller
剩余的工作相对简单,只要在UserController中去除内存中Map及相关代码,然后改为通过UserService获取数据并返回即可:
package cn.icexmoon.my_first_app.controller;
import cn.icexmoon.my_first_app.model.Result;
import cn.icexmoon.my_first_app.model.User;
import cn.icexmoon.my_first_app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
("/user")
public class UserController {
UserService userService;
("")
public String addUser( User user) {
long newId = userService.addUser(user);
Result result = new Result();
result.setData(newId);
return result.toString();
}
("/{id}")
public Result deleteUser( long id) {
Result result = new Result();
User user = userService.getUser(id);
if (user == null) {
result.setSuccess(false);
result.setMsg("no this person.");
return result;
}
userService.deleteUser(id);
result.setMsg("delete success.");
return result;
}
("/{id}")
public Result updateUser( long id, User user) {
Result result = new Result();
User u = userService.getUser(id);
if (u == null) {
result.setSuccess(false);
result.setMsg("no this person.");
return result;
}
user.setId(id);
userService.updateUser(user);
return result;
}
("/{id}")
public Result getUser( long id) {
Result result = new Result();
User user = userService.getUser(id);
if (user == null) {
result.setSuccess(false);
result.setMsg("no this person.");
return result;
}
result.setData(user);
return result;
}
("")
public String getUsers() {
Result result = new Result();
result.setData(userService.getUsers());
return result.toString();
}
}
这里同样以@Autowired注解的方式引入UserService,并不需要我们自行对其初始化。
好了,现在再试试通过HTTP客户端模拟访问,即使应用重启数据也依然存在。
谢谢阅读。
本篇文章的最终代码可以从获取。

文章评论