# 第七章 使用JPA操作数据库
本章主要介绍如何在Spring Boot的Web应用中使用Mysq数据库,也充分展示Spring Boot的优势(尽可能少的代码和配置).
数据访问层我们将使用Spring Data JPA和Hibernate(JPA的实现之一).
本章我们使用数据库名称为lightsword;
数据表名ls_user;
字段包括id, username, password, gmt_create, gmt_update。(其中id为主健,int类型, username和password分别为用户名和密码,都是varchar类型, gmt_create为创建日期,datetime类型,gmt_update为更新时间,datetime类型)
### 配置pom.xml文件
打开pom.xml文件,增加如下依赖:
~~~
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
~~~
### 配置文件application.properties
在src/main/resources/application.properties中配置数据库,包括url,用户名,密码和driverClassName:
~~~
spring.datasource.url = jdbc:mysql://localhost:3306/lightsword?useUnicode=true&characterEncoding=UTF8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
~~~
上文中的数据库配置,你需要换成你的数据库的地址和用户名密码。
### 创建实体类
在src->main->java->lightsword下,创建一个package,名称为entity。在entity包下创建java类,名称为User,这就是我们的实体类。User.java内容如下:
~~~
package lightsword.entity;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "ls_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String username;
private String password;
private Date gmtCreate;
private Date gmtUpdate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getGmtCreate() {
return gmtCreate;
}
public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}
public Date getGmtUpdate() {
return gmtUpdate;
}
public void setGmtUpdate(Date gmtUpdate) {
this.gmtUpdate = gmtUpdate;
}
}
~~~
这里我们使用了两个注解@Entity, @Table。
@Entity表示是一个实体类。
@Table用于对应数据库中的表名。
### 创建Dao层
在src->main->java->lightsword下,创建一个package,名称为dao。在dao包下创建java接口,名称为UserDao,这就是我们的数据访问层。
实体的数据访问层UserDao非常简单,只需要继承CrudRespositroy即可,CrudRespositroy已经实现了save,delete,deleteAll,findOne和findAll.
(比较神奇的时这些方法其实CrudRespositroy中其实并没有实现,并且通过对dao层的方法的命名还可以实现新的方法).
当然,如果基本的CRUD方法满足不了我们稍微复杂一些的sql查询,我们可以直接定义sql查询语句,绑定dao层的方法.
UserDao.java内容如下:
```
package lightsword.dao;
import lightsword.entity.User;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface UserDao extends CrudRepository<User, Integer> {
List<User> findAll();
}
```
findAll()是CrudRepository自带的方法。
### 控制器
回到MainController.java
我们借助@Autowired注解,自动装配Dao层。修改一下hello方法,将用户表的数据查询出来后显示在前端。
完整的MainController.java内容如下:
```
package lightsword.controller;
import lightsword.dao.UserDao;
import lightsword.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
public class MainController {
@Autowired
private UserDao userDao;
@RequestMapping("/hello")
public ModelAndView hello(Model model){
ModelAndView modelAndView = new ModelAndView("index");
String hello = "Hello world";
model.addAttribute("hello", hello);
List<User> userList = userDao.findAll();
model.addAttribute("userList", userList);
return modelAndView;
}
@RequestMapping(value = "/testGet", method = RequestMethod.GET)
@ResponseBody
public String testGet(){
return "this is a get request data";
}
@RequestMapping(value = "/testPost", method = RequestMethod.POST)
@ResponseBody
public String testPost(@RequestParam String username){
String result = "hello " + username;
return result;
}
}
```
最后,更新一下src->main->resources->templates目录下的index.html文件。这里为了美化前端,我们引入bootstrap框架。
在resources->static目录下新建一个css目录,将bootstrap.min.css拷贝到css目录里。将bootstrap.min.js拷贝到static->js目录下。(没有这两个文件的可到bootstrap官网下载)
然后修改我们的index.html文件,引入bootstrap文件,定义一个table用于显示ls_user表的数据。我们使用velocity的#foreach语法将数据显示。
为了展示:我们先在数据表ls_user里手动插入几条测试数据。
完整的index.html内容如下:
```
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="/css/bootstrap.min.css" rel="stylesheet">
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</head>
<body>
<h1>$hello</h1>
<div id="container-get" style="border:1px solid red; width:300px; height:100px;">
loading...
</div>
<div id="container-post" style="border:1px solid green; width:300px; height:100px;">
loading...
</div>
<table class="table table-striped">
<thead>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
</thead>
<tbody>
#foreach($user in $userList)
<tr>
<td>$user.id</td>
<td>$user.username</td>
<td>$user.password</td>
</tr>
#end
</tbody>
</table>
</body>
</html>
<script type="text/javascript">
$(function(){
$.get('/testGet', function(data){
$("#container-get").html(data);
});
var username = "lightsword";
$.post('/testPost', {username:username}, function(data){
$("#container-post").html(data);
});
});
</script>
```
### 运行测试
运行lighsword.java后,浏览器访问:http://127.0.0.1:9527/hello
结果显示了我们手动插入的两条测试数据。