# 第七章 使用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
結果顯示了我們手動插入的兩條測試數據。