Spring-Data-JPA嚐鮮:快速搭建CRUD+分頁後臺實例

https://mp.weixin.qq.com/s/D12izOGIjhY8I1ebgQyLMQ

Spring-Data-JPA嚐鮮:快速搭建CRUD+分頁後臺實例


image.png

前言:因爲以前沒有接觸過Hibernate框架,可是最近看一些博客深深被它的「效率」所吸引,因此這就來跟你們一塊兒就着一個簡單的例子來嚐嚐Spring全家桶裏自帶的JPA的鮮java

Spring-DATA-JPA 簡介

JPA(Java Persistence API)是Sun官方提出的Java持久化規範。它爲Java開發人員提供了一種對象/關聯映射工具來管理Java應用中的關係數據。他的出現主要是爲了簡化現有的持久化開發工做和整合ORM技術,結束如今Hibernate,TopLink,JDO等ORM框架各自爲營的局面。值得注意的是,JPA是在充分吸取了現有Hibernate,TopLink,JDO等ORM框架的基礎上發展而來的,具備易於使用,伸縮性強等優勢。從目前的開發社區的反應上看,JPA受到了極大的支持和讚賞,其中就包括了Spring與EJB3.0的開發團隊。mysql

注意:JPA是一套規範,不是一套產品,那麼像Hibernate,TopLink,JDO他們是一套產品,若是說這些產品實現了這個JPA規範,那麼咱們就能夠叫他們爲JPA的實現產品。git

Spring Data JPA 是 Spring 基於 ORM 框架、JPA 規範的基礎上封裝的一套JPA應用框架,可以使開發者用極簡的代碼便可實現對數據的訪問和操做。它提供了包括增刪改查等在內的經常使用功能,且易於擴展!學習並使用 Spring Data JPA 能夠極大提升開發效率!(spring data jpa讓咱們解脫了DAO層的操做,基本上全部CRUD均可以依賴於它來實現github

摘自:springboot(五):spring data jpa的使用——純潔的微笑web

Hibernate 和 MyBatis 簡單對比

因爲JPA底層幹活的仍然是Hibernate框架,而咱們以前學習的只有MyBatis相關的東西,因此在嚐鮮以前仍是有必要簡單瞭解一下二者的區別:spring

Hibernate的優點:sql

  • Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射。數據庫

  • Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。緩存

  • Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。springboot

  • Hibernate有更好的二級緩存機制,可使用第三方緩存。MyBatis自己提供的緩存機制不佳。

MyBatis的優點:

  • MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。

  • MyBatis容易掌握,而Hibernate門檻較高。

簡單總結:

  • MyBatis:小巧、方便、高效、簡單、直接、半自動化

  • Hibernate:強大、方便、高效、複雜、間接、全自動化

引用自:【持久化框架】Mybatis與Hibernate的詳細對比——高亮

CRUD + 分頁後臺實例

下面咱們來快速搭建一個使用Spring-DATA-JPA的CRUD+分頁後臺實例,而且咱們會直接使用到RESTful API(不熟悉的同窗[戳這裏]())

第一步:新建SpringBoot項目

打開IDEA新建一個SpringBoot項目,不熟悉SpringBoot的同窗請右轉:【傳送門】,而後在pom.xml中添加如下依賴:

<!-- mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.21</version>
</dependency>

<!-- jpa-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

而後把application.properties弄成這個樣子:

#數據庫
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#顯示SQL語句
spring.jpa.show-sql=true
#不加下面這句則默認建立MyISAM引擎的數據庫
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#本身重寫的配置類,默認使用utf8編碼
spring.jpa.properties.hibernate.dialect=com.wmyskxz.demo.config.MySQLConfig

spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性,其主要做用是:自動建立、更新、驗證數據庫表結構。該參數的幾種配置以下:

  • create:每次加載hibernate時都會刪除上一次的生成的表,而後根據你的model類再從新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是致使數據庫表數據丟失的一個重要緣由。

  • create-drop:每次加載hibernate時根據model類生成表,可是sessionFactory一關閉,表就自動刪除。

  • update:最經常使用的屬性,第一次加載hibernate時根據model類會自動創建起表的結構(前提是先創建好數據庫),之後加載hibernate時根據model類自動更新表結構,即便表結構改變了但表中的行仍然存在不會刪除之前的行。要注意的是當部署到服務器後,表結構是不會被立刻創建起來的,是要等應用第一次運行起來後纔會。

  • validate:每次加載hibernate時,驗證建立數據庫表結構,只會和數據庫中的表進行比較,不會建立新表,可是會插入新值。

而後新建一個【config】包,建立一個【MySQLConfig】類(上面的spring.jpa.properties.hibernate.dialect屬性就要配置這裏的類全路徑):

package com.wmyskxz.demo.config;

import org.hibernate.dialect.MySQL5InnoDBDialect;

public class MySQLConfig extends MySQL5InnoDBDialect {
    @Override
    public String getTableTypeString() {
        return "ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
}

第二步:建立好須要的數據庫

打開SQL服務,建表語句也很簡單啦:

create database testdb;

第三步:建立實體類

實體類映射的其實是數據庫表的結構,在適當的包目錄下(例如【entity】)下建立好實體類:

package com.wmyskxz.demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity // 代表這是個實體類
public class User {

    @Id // 代表這個屬性是主鍵
    @GeneratedValue // 自增加
    private long id;
    @Column(nullable = false, unique = true)    // 不容許爲空,屬性惟一
    private String username;
    @Column(nullable = false)   // 不容許爲空
    private String password;

    // getter and setter
}

第四步:DAO層

新建一個【repository】包,而後新建一個【UserRepository】接口,並繼承JpaRepository類:

package com.wmyskxz.demo.repository;

import com.wmyskxz.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<UserLong{
}

繼承JpaRepository須要傳入兩個參數,一個是實體類User一個是主鍵的類型Long,而凡是繼承了JpaRepository類的就會自動實現不少內置的方法,包括增刪改查,以及使用默認支持的Pageable對象來進行分頁,默認的方法大體以下:

public interface JpaRepository<TIDextends PagingAndSortingRepository<TID>, QueryByExampleExecutor<T{
    List<T> findAll();
    List<T> findAll(Sort var1);
    List<T> findAllById(Iterable<ID> var1);
    <S extends T> List<S> saveAll(Iterable<S> var1);
    void flush();
    <S extends T> saveAndFlush(S var1);
    void deleteInBatch(Iterable<T> var1);
    void deleteAllInBatch();
    getOne(ID var1);
    <S extends T> List<S> findAll(Example<S> var1);
    <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

第五步:Controller層

新建【controller】包,新建一個【UserController】類,編寫簡單的增刪改查代碼:

package com.wmyskxz.demo.controoler;

import com.wmyskxz.demo.entity.User;
import com.wmyskxz.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController // 代表這是一個Controller並返回JSON格式
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/getOne")
    public Optional<User> getOneUserById(@RequestParam long id) {
        return userRepository.findById(id);
    }

    @GetMapping("/all")
    public Iterable<User> getAllUsers(@RequestParam(value = "page", defaultValue = "0") int page,
                                      @RequestParam(value = "size", defaultValue = "5") int size) 
{
        page = page < 0 ? 0 : page;// 若是page爲負數則修改成0,防止在首頁點擊上一頁發生錯誤
        Sort sort = new Sort(Sort.Direction.DESC, "id");// 按id倒敘排列
        return userRepository.findAll(new PageRequest(page, size, sort));
    }

    @PostMapping("/add")
    public String addUser(@RequestParam String username,
                          @RequestParam String password)
 
{
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        userRepository.save(user);// 注意這裏是save
        return "Saved";
    }

    @DeleteMapping("/delete")
    public String deleteUserById(@RequestParam long id) {
        userRepository.deleteById(id);
        return "Deleted";
    }

    @PutMapping("/update")
    public String updateUser(User user) {
//        User user = new User();
//        user.setId(id);
//        user.setUsername(username);
//        user.setPassword(password);
        userRepository.save(user);
        return "Updated";
    }
}

上面就直接使用@Autowired自動引入了繼承了JpaRepository的UserRepository接口,咱們使用它默認的方法已經足夠完成咱們的基礎功能了,值得一提的是咱們的getAllUsers(...)方法,它往findAll()方法裏傳入了一個Pageable對象,這是Spring Data庫中定義的一個接口,是全部分頁相關信息的一個抽象,經過該接口,咱們能夠獲得和分頁相關的全部信息(例如pageNumberpageSize等),這樣Jpa就可以經過Pageable參數來獲得一個帶分頁信息的Sql語句。

固然上面咱們是經過本身建立了一個Pageable對象,Spring也支持直接獲取Pageable對象,能夠把上面的getAllUsers(...)方法改寫成下面這樣:

@GetMapping("/all")
public Iterable<User> getAllUsers(@PageableDefault(value = 5, sort = {"id"}, direction = Sort.Direction.DESC) 
                                              Pageable pageable) 
{
    return userRepository.findAll(pageable);
}

默認從第0頁開始,也能夠本身傳入一個page參數,跟上面的是同樣的。

第六步:運行項目

上面咱們就快速搭建起來了一個基於Spring Boot和JPA的REST風格的後臺增刪改查實例,咱們把項目跑起來,能夠看到數據庫自動建立了一些表:

image.png

JPA幫咱們建立的user表的建立SQL以下:

CREATE TABLE `user` (
  `id` bigint(20NOT NULL,
  `password` varchar(255NOT NULL,
  `username` varchar(255NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_sb8bbouer5wak8vyiiy4pf2bx` (`username`)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

使用REST測試工具測試

徹底符合咱們的要求,而後咱們使用一些REST的測試工具,來測試上面的功能是否都能正確運行,好比我這裏使用的【Restlet Client】,在Chrome商店就能夠下載到。

`/all`地址測試:

首先先來測試一下http://localhost:8080/all地址,因爲如今數據庫仍是空的,因此能夠看到返回以下:

{
    "content": [
    ],
    "pageable": {
        "sort": {
            "sorted"true,
            "unsorted"false,
            "empty"false
        },
        "offset"0,
        "pageNumber"0,
        "pageSize"5,
        "unpaged"false,
        "paged"true
    },
    "totalElements"0,
    "last"true,
    "totalPages"0,
    "number"0,
    "size"5,
    "sort": {
        "sorted"true,
        "unsorted"false,
        "empty"false
    },
    "numberOfElements"0,
    "first"true,
    "empty"true
}

添加用戶測試:

而後咱們使用

http://localhost:8080/add?username=wmyskxz&password=123地址,添加幾個相似的用戶信息: image.png

能夠看到返回正確的Saved信息:

image.png

`/getOne`地址測試:

咱們就直接使用http://localhost:8080/getOne?id=1來獲取剛纔添加的用戶,能夠看到返回正確的數據:

{
    "id"1,
    "username""wmyskxz",
    "password""123"
}

修改用戶測試:

而後咱們使用http://localhost:8080/update?id=1&username=wmyskxz&password=123456來模擬進行用戶密碼的修改:

image.png

能夠看到正確的更新信息Updated,再次查詢用戶,也能看到正確的數據:

{
    "id"1,
    "username""wmyskxz",
    "password""123456"
}

分頁測試:

咱們使用添加功能爲數據庫添加5條以上的數據,而後進行一次查詢/all,能夠看到可以按照id倒敘排列後返回5條數據:

image.png

數據庫的狀況

返回的JSON數據以下:

{
    "content": [
        {
            "id"10,
            "username""wmyskxz8",
            "password""123"
        },
        {
            "id"9,
            "username""wmyskxz7",
            "password""123"
        },
        {
            "id"8,
            "username""wmyskxz6",
            "password""123"
        },
        {
            "id"7,
            "username""wmyskxz5",
            "password""123"
        },
        {
            "id"6,
            "username""wmyskxz4",
            "password""123"
        }
    ],
    "pageable": {
        "sort": {
            "sorted"true,
            "unsorted"false,
            "empty"false
        },
        "offset"0,
        "pageNumber"0,
        "pageSize"5,
        "unpaged"false,
        "paged"true
    },
    "totalElements"9,
    "last"false,
    "totalPages"2,
    "number"0,
    "size"5,
    "sort": {
        "sorted"true,
        "unsorted"false,
        "empty"false
    },
    "numberOfElements"5,
    "first"true,
    "empty"false
}

刪除用戶測試:

使用地址http://localhost:8080/delete?id=1來刪除ID爲1的用戶:

image.png

能正確看到Deleted信息,並查看數據可以看到數據已經被刪除了。


以上,咱們就快速搭建好了一個CRUD+分頁的後臺實例,還用了比較流行的RESTful風格,粗略的感覺了一下JPA的方便,仍是挺爽的..沒有複雜的Mapper文件,不用自動生成實體,甚至不用管SQL,只須要專一在邏輯上就好了,其實簡單使用的話以上的東西也能應付一些常見的場景了,後期再深刻了解了解吧!

參考資料:
springboot(五):spring data jpa的使用——純潔的微笑
springboot(十五):springboot+jpa+thymeleaf增刪改查示例——純潔的微笑
Spring Boot中使用Spring-data-jpa讓數據訪問更簡單、更優雅——程序猿DD

歡迎轉載,轉載請註明出處!   
簡書ID:@我沒有三顆心臟  
github:wmyskxz  
歡迎關注公衆微信號:wmyskxz
分享本身的學習 & 學習資料 & 生活
想要交流的朋友也能夠加qq羣:3382693


我沒有三顆心臟

讚揚二維碼喜歡做者

相關文章
相關標籤/搜索