【SpringBoot系列04】SpringBoot之使用JPA完成簡單的rest api

一、 前言

在前面我們已經知道在springboot中如何使用freemarkthymeleaf之類的視圖模板引擎去渲染我們的視圖頁面,但是沒涉及跟數據庫交互的東西,所以今天在這裏我們將介紹了一下如何在springboot中通過spring data jpa操作mysql數據庫,並且構建一套簡單的rest api接口。
## 1.1、Spring Data Jpa 介紹
Spring Data JPA是Spring基於Hibernate開發的一個JPA框架。如果用過Hibernate或者MyBatis的話,就會知道對象關係映射(ORM)框架有多麼方便。但是Spring Data JPA框架功能更進一步,爲我們做了 一個數據持久層框架幾乎能做的任何事情。並且提供了基礎的增刪改查方法,具體api請看官網

2.2

REST是所有Web應用都應該遵守的架構設計指導原則。
Representational State Transfer,翻譯是”表現層狀態轉化”。
面向資源是REST最明顯的特徵,對於同一個資源的一組不同的操作。資源是服務器上一個可命名的抽象概念,資源是以名詞爲核心來組織的,首先關注的是名詞。REST要求,必須通過統一的接口來對資源執行各種操作。對於每個資源只能執行一組有限的操作。(7個HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)
關於rest api如何涉及我也是從阮一峯老師那裏學習的。

二、目標

首先我們有一個user表,我們希望能通過構建出對應的rest api對錶中的數據完成增刪改查操作。
jpa的依賴如下

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    </dependencies>

接下來那麼第一步就是創表了
1、創表
由於我們使用的spring data jpa 而jpa的底層實現是hibernate,用過hibernate的同學知道 hibernate可以通過實體類逆向創建表,只需要配置一下ddl-auto 就可以
所以我們需要在application.yml配置一下

server:
  port: 8989
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

在上面的配置文件中 我們配置了一個數據源跟tomcat端口還有jpa的配置。其中 show-sql: true 代表會在日誌中打印我們操作的sql、
而另外 ddl-auto有四個值可選,分別是
* create 啓動時刪數據庫中的表,然後創建,退出時不刪除數據表
* create-drop 啓動時刪數據庫中的表,然後創建,退出時刪除數據表 如果表不存在報錯
* update 最常用的屬性,第一次加載hibernate時根據model類會自動建立起表的結構(前提是先建立好數據庫),以後加載hibernate時根據 model類自動更新表結構,即使表結構改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到服務器後,表結構是不會被馬上建立起來的,是要等 應用第一次運行起來後纔會。
* validate 項目啓動表結構進行校驗 如果不一致則報錯


所以這裏我們希望當表創建成功後 下次啓動數據還在我們就選擇了update模式,其次我們需要在本地的mysql數據庫新建一個test數據庫。
接下來我們需要編寫的我們實體類User.javahibernate將會通過實體類的結構在test數據庫中創建一個對應的user
新建包entity 創建User.java代碼如下:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) 
@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;

    /**
     * 用戶名
     */
    @Column(name = "username", nullable = true, length = 32)
    private String username;

    /**
     * 密碼
     */
    @Column(name = "password", nullable = true, length = 32)
    private String password;

    /**
     * 年齡
     */
    @Column(name = "age", nullable = true, length = 11)
    private Integer age;

    /**
     * 性別 1=男 2=女 其他=保密
     */
    @Column(name = "sex", nullable = true, length = 11)
    private Integer sex;


    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

至此,我們的user表也算是創建好了,當我們的程序第一個啓動的時候jpa會自動在test數據庫中創建與之對應的表。


2、構建rest api
這裏我們需要構建如下的rest api

url method 介紹
/user/ get 獲取所有的用戶信息
/user/id/{id} get 根據id獲取用戶信息
/user/username/{username} get 根據username獲取用戶信息
/user post 新增用戶信息
/user put 更新用戶信息
/user/id/{id} delete 根據id刪除用戶信息

那麼這就是我們需要構建的rest api,那麼對應的由mvc模式可知我們的rest apicontroller層的,所以我們的servicerepository層(備註在使用 jpa的時候我們喜歡把dao層命名爲repository)需要提供對應的接口。
首先我們首先需要編寫UserRepository接口,並且讓它基礎JpaRepository接口

新建包repository 創建UserRepository.java代碼如下:

public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 根據用戶名查找用戶信息
     * @param username
     * @return
     */
    User findUserByUsername(String username);

}

解釋一下上面的代碼,爲什麼只有一個方法,而前面我們是五個接口,因爲是在JpaRepository中提供較爲基礎的增刪改查方法,我們無需編寫就看使用。如果大家不信按住ctrl點擊JpaRepository看源碼就知道了。
image.png
從上面就可以看出JpaRespository提供了哪些基礎方法了。怎麼樣 是不是覺得很方便。那麼接下來的第二點就Jpa可以根據你的命名規則來推斷你這個方法作用,簡單的來說findUserByUsername 根據這個方法名,jpa可以知道這個方法是通過用戶名去查找用戶。 具體的規則大家可以看文檔
image.png
如果大家用的idea的話,那麼它會用智能提示功能,如圖
image.png
所以我們只需要編寫方法名就可以輕輕鬆鬆的實現我們的查詢方法,怎麼樣jpa是不是特別簡單,但是需要注意的是方法名一定要命名規範,不要嫌太長了。
接下來就是編寫我們的service層了,
新建service包創建UserService.java代碼如下:

public interface UserService {

    /**
     * 添加用戶信息
     * @param user
     * @return
     */
    User saveUser(User user);

    /**
     * 更新用戶信息
     * @param user
     */
    User updateUser(User user);

    /**
     * 根據id獲取用戶
     * @param id
     * @return
     */
    User getById(Long id);

    /**
     * 根據名稱獲取用戶
     * @param username
     * @return
     */
    User getByUserName(String username);

    /**
     * 查詢所有用戶
     * @return
     */
    List<User> queryAll();

    /**
     * 根據id刪除用戶信息
     * @param id
     */
    void deleteById(Long id);
}

接下里就下service的實現類,帶service包下新建impl包並且創建實現類UserServiceImpl.java 代碼如下

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User saveUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public User updateUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public User getById(Long id) {
        return userRepository.getOne(id);
    }

    @Override
    public User getByUserName(String username) {
        return userRepository.findUserByUsername(username);
    }

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

    @Override
    public void deleteById(Long id) {
        userRepository.deleteById(id);
    }
}

那麼緊接着就是控制層的代碼了,新建controller包,並且創建UserController.java

@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User save(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @PutMapping
    public User update(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @DeleteMapping(value = "/id/{id}")
    public String delete(@PathVariable  Long id) {
        userService.deleteById(id);
        return "刪除成功";
    }

    @GetMapping(value = "/id/{id}")
    public User findById (@PathVariable Long id) {
        return userService.getById(id);
    }

    @GetMapping(value = "/username/{username}")
    public User findByUsername (@PathVariable String username) {
        return userService.getByUserName(username);
    }

    @GetMapping(value = "/")
    public List<User> findAll () {
        return userService.queryAll();
    }
}

這樣我們就完成了一個簡單的rest api了啊。
接下來我們來測試一下把。
3、測試
由於我們這裏測試的是rest api普通的瀏覽器是沒法支持 post delet put方式的訪問的,所以這裏我們就用postman來測試。
1、首先我們看到test數據庫中現在是一張表都沒有的
image.png
啓動程序,注意觀察日誌。
image.png

我們看到了日誌打印了創建表的ddl那麼我們再看看數據庫中有沒有表
image.png
此時我們看到了有兩張表,一張是我們user表,而另一張就是主鍵生成序列表。
接下來就開始我們的rest api測試了。
首先測試新增用戶
打開postman

image.png
選擇post模式,輸入訪問的url,然後選擇body中的raw,因爲我們使用的@RequestBody註解,所以我們選擇raw中的Json,如圖
image.png
因爲我們的id是自增的,所以我們不要輸入,直接點擊send訪問,如果返回的數據有id那麼就是代表新增成功。如下圖就是新增成功。
image.png
打開數據庫中的user表,看看數據有沒有保存成功。
image.png
由圖可知,保存成功。
接下來我們就多添加幾條數據。
那麼我們測試一下查詢所有數據的方法。操作如圖
image.png
我們剛剛一共添加三條數據,全部都查詢出來了。
我們繼續測試一下修改方法把。我們把id爲2的數據密碼修改爲跟用戶名一樣,具體操作如圖,
image.png
點擊send操作成功,我們用根據id查詢的方法來查詢一下剛剛id爲2的數據有沒有修改成功,那麼我們查詢一下id爲2的數據,操作如圖。
image.png
由圖中可以看到我們的修改是成功的,用戶名跟密碼已經一樣的,那麼代表我們的根據id查詢方法也是沒問題的。那麼另外幾個方法我們不測試了,留給大家測試。

三、總結

這裏我們通過這次選擇對於jpa的使用有了一個初步的瞭解,並且對於rest api的規範也有了個瞭解。
最後配套教程的代碼全部在這裏
github https://github.com/YuKongEr/SpringBoot-Study

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章