Spring Data Jpa

大暑發表於2020-05-29

Spring Data Jpa 簡介

  JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0後提出的Java持久化規範(JSR 338,這些介面所在包為javax.persistence,詳細內容可參考https://github.com/javaee/jpa-spec

  JPA的出現主要是為了簡化持久層開發以及整合ORM技術,結束Hibernate、TopLink、JDO等ORM框架各自為營的局面。JPA是在吸收現有ORM框架的基礎上發展而來,易於使用,伸縮性強。總的來說,JPA包括以下3方面的技術:

  • ORM對映後設資料: 支援XML和註解兩種後設資料的形式,後設資料描述物件和表之間的對映關係
  • API: 操作實體物件來執行CRUD操作
  • 查詢語言: 通過物件導向而非面向資料庫的查詢語言(JPQL)查詢資料,避免程式的SQL語句緊密耦合
 

Spring Data Jpa官方解釋

  連線:https://spring.io/projects/spring-data-jpa#overview

  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  
 
 
  
  
  Spring Data JPA是Spring Data家族的一部分,可以輕鬆實現基於JPA的儲存庫。 此模組處理對基於JPA的資料訪問層的增強支援。 它使構建使用資料訪問技術的Spring驅動應用程式變得更加容易。
  在相當長的一段時間內,實現應用程式的資料訪問層一直很麻煩。 必須編寫太多樣板程式碼來執行簡單查詢以及執行分頁和審計。 Spring Data JPA旨在通過減少實際需要的工作量來顯著改善資料訪問層的實現。 作為開發人員,您編寫repository介面,包括自定義查詢器方法,Spring將自動提供實現。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Hibernate、Jpa、Spring Data Jpa三者之間的關係

 Hibernate

  Hibernate是一個開放原始碼的物件關係對映框架,它對JDBC進行了非常輕量級的物件封裝,它將POJO與資料庫表建立對映關係,是一個全自動的orm框架,hibernate可以自動生成SQL語句,自動執行,使得Java程式設計師可以隨心所欲的使用物件程式設計思維來操縱資料庫。

 JPA

  JPA全稱是Java Persistence API,即java持久化API,是sun公司推出的一套基於ORM的規範,內部由一系列的介面和抽象類構成

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

JPA與Hibetnate的關係

  JPA和Hibernate的關係就像JDBC和JDBC驅動的關係,JPA是規範,Hibernate除了作為ORM框架之外,它也是一種JPA實現。JPA怎麼取代Hibernate呢?JDBC規範可以驅動底層資料庫嗎?答案是否定的,也就是說,如果使用JPA規範進行資料庫操作,底層需要hibernate作為其實現類完成資料持久化工作。

Spring Data jpa

  Spring Data JPA 讓我們解脫了DAO層的操作,基本上所有CRUD都可以依賴於它來實現,在實際的工作工程中,推薦使用Spring Data JPA + ORM(如:hibernate)完成操作,這樣在切換不同的ORM框架時提供了極大的方便,同時也使資料庫層操作更加簡單,方便解耦

 總結:

  JPA是一種規範,Hibernate實現了JPA規範,即Hibernate為JPA的一種實現;而Spring Data JPA是對JPA進行更高階的封裝,讓其dao編碼變得更簡單。
 

Spring Boot整合Spring Data Jpa

  匯入依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

 

相關配置

server:
  port: 9001
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/practice?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: 123456
  jpa:
    database: mysql
    show-sql: true
    open-in-view: true
    hibernate:
      ddl-auto: update

   ddl-auto

  • create:每次執行程式時,都會重新建立表,故而資料會丟失
  • create-drop:每次執行程式時會先建立表結構,然後待程式結束時清空表
  • upadte:每次執行程式,沒有表時會建立表,如果物件發生改變會更新表結構,原有資料不會清空,只會更新(推薦使用)
  • validate:執行程式會校驗資料與資料庫的欄位型別是否相同,欄位不同會報錯
  • none: 禁用DDL處理

Spring Data Jpa的使用

  Spring Data Jpa UML類圖

 

 

簡單的REST CRUD示例

  實體類
package com.jpa.product.entity;

        import lombok.Data;

        import javax.persistence.*;
        import java.math.BigDecimal;

/**
 * @author: MR.LIU
 * @description:
 * @date: 2020/5/29
 * @time: 22:17
 */
@Data
@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "product_name")
    private String productName;

    @Column(name = "price")
    private BigDecimal price;

    @Column(name = "description")
    private String description;

    @Column(name = "status")
    private Integer status;

    @Column(name = "caption")
    private String caption;

    @Column(name = "stock")
    private Integer stock;
}

 

  一般簡單的Demo示例中只會使用@GeneratedValue(strategy = GenerationType.IDENTITY)這種主鍵自增的策略,而實際資料庫中表欄位主鍵型別很少是int型的

JPA自帶的幾種主鍵生成策略

  • TABLE: 使用一個特定的資料庫表格來儲存主鍵
  • SEQUENCE: 根據底層資料庫的序列來生成主鍵,條件是資料庫支援序列。這個值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫的序列)
  • IDENTITY: 主鍵由資料庫自動生成(主要是支援自動增長的資料庫,如mysql)
  • AUTO: 主鍵由程式控制,也是GenerationType的預設值

  dao層
package com.jpa.product.dao;

import com.jpa.product.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
 * @author: MR.LIU
 * @description: 資料層
 * @date: 2020/5/29
 * @time: 22:34
 */
public interface ProductDao extends JpaRepository<Product,Long>, JpaSpecificationExecutor<Product> {
}

 

  service層

package com.jpa.product.service;

import com.jpa.product.entity.Product;

/**
 * @author: MR.LIU
 * @description: 介面層
 * @date: 2020/5/29
 * @time: 22:37
 */
public interface ProductService {
    /**
     * 根據id查詢
     * @param id
     * @return
     */
    Product findById(Long id);

    /**
     * 儲存
     * @param product
     * @return
     */
    void save(Product product);

    /***
     * 修改
     * @param product
     * @return
     */
    void update(Product product);

    /**
     * 刪除
     * @param id
     * @return
     */
    void delete(Long id);
}

  

  impl層

package com.jpa.product.service.impl;

import com.jpa.product.dao.ProductDao;
import com.jpa.product.entity.Product;
import com.jpa.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author: MR.LIU
 * @description:
 * @date: 2020/5/29
 * @time: 22:41
 */
@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductDao productDao;

    @Override
    public Product findById(Long id) {
        return productDao.findById(id).get();
    }

    @Override
    public void save(Product product) {
         productDao.save(product);
    }

    @Override
    public void update(Product product) {
        productDao.save(product);
    }

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

 

  controller層
 
package com.jpa.product.controller;

import com.jpa.product.entity.Product;
import com.jpa.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author: MR.LIU
 * @description:
 * @date: 2020/5/29
 * @time: 22:47
 */
@RestController
@RequestMapping(value = "/product")
public class ProductController {
    @Autowired
    private ProductService productService;

    @GetMapping(value = "/{id}")
    public Product getProduct(@PathVariable Long id) {
        return productService.findById(id);
    }

    @PostMapping(value = "/save")
    public String saveProduct(@RequestBody Product product){
        productService.save(product);
        return "儲存成功";
    }

}

 

  測試
http://localhost:9001/product/1

  成功查詢

 

 

 
 
 
 
 
 
 
 
 
 
 

相關文章