Spring Boot 入門系列(七) 使用 JPA

文章使用版本為 Spring Boot 2.1.x

前言

JPA是Java Persistence API的簡稱,是一種標(biāo)準(zhǔn),具體實現(xiàn)交由各個廠商實現(xiàn)。Spring Data JPA 對其提供支持,內(nèi)部實現(xiàn)是Hibernate。

使用JPA開發(fā)代碼非常方便,只要寫一個接口繼承 JpaRepository 就可以實現(xiàn)基本的增刪改查的功能,比如下面這樣

public interface UserRepository extends JpaRepository<User, String> {

}

在大部分情況下都是使用單表操作時,使用JPA也是一個不錯的選擇,下面我們就來一起學(xué)習(xí)下吧。

添加依賴

        <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>

application.yml

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/spring_boot_learn?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true&useSSL=true
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    hikari:
      minimum-idle: 2
      maximum-pool-size: 5
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

datasource的部分就不多講了,我們主要來看一下jpa的配置部分

  • jpa.show-sql:這個很明顯是控制是否顯示SQL語句的,開發(fā)時我們可以選擇true
  • jpa.hibernate.ddl-auto:這個是用來控制數(shù)據(jù)庫表的生成策略,有以下幾種值
    • create:每次加載hibernate時都會刪除上一次的生成的表,然后根據(jù)你的model類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執(zhí)行,這就是導(dǎo)致數(shù)據(jù)庫表數(shù)據(jù)丟失的一個重要原因。
    • create-drop:每次加載hibernate時根據(jù)model類生成表,但是sessionFactory一關(guān)閉,表就自動刪除。
    • update:最常用的屬性,第一次加載hibernate時根據(jù)model類會自動建立起表的結(jié)構(gòu)(前提是先建立好數(shù)據(jù)庫),以后加載hibernate時根據(jù)model類自動更新表結(jié)構(gòu),即使表結(jié)構(gòu)改變了但表中的行仍然存在不會刪除以前的行。要注意的是當(dāng)部署到服務(wù)器后,表結(jié)構(gòu)是不會被馬上建立起來的,是要等應(yīng)用第一次運(yùn)行起來后才會。
    • validate:每次加載hibernate時,驗證創(chuàng)建數(shù)據(jù)庫表結(jié)構(gòu),只會和數(shù)據(jù)庫中的表進(jìn)行比較,不會創(chuàng)建新表,但是會插入新值。

雖然可以讓程序自動生成表結(jié)構(gòu),但是我還是建議手寫建表語句。

CREATE SCHEMA IF NOT EXISTS `spring_boot_learn` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

CREATE TABLE IF NOT EXISTS `spring_boot_learn`.`user` (
  `id` VARCHAR(37) NOT NULL COMMENT 'UUID',
  `username` VARCHAR(128) NOT NULL COMMENT '用戶名',
  `age` INT(10) unsigned NOT NULL COMMENT '年齡',
  PRIMARY KEY (`id`)  COMMENT ''
  )
ENGINE = InnoDB
COMMENT = '用戶表';

創(chuàng)建實體

package org.schhx.springbootlearn.entity;

import lombok.Data;
import lombok.experimental.Accessors;

import javax.persistence.Entity;
import javax.persistence.Id;

@Data
@Accessors(chain = true)
@Entity
public class User {
    @Id
    private String id;

    private String username;

    private Integer age;

}

@Entity 表明是一個實體類
@Id 用來指明主鍵,如果使用自增主鍵,可以在主鍵上加上@GeneratedValue

創(chuàng)建數(shù)據(jù)訪問接口

package org.schhx.springbootlearn.dao;

import org.schhx.springbootlearn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface UserRepository extends JpaRepository<User, String> {

    List<User> findByUsername(String username);
}

通過查看 JpaRepository 的源碼我們可以發(fā)現(xiàn),通用的增刪改查的方法都已經(jīng)有了,當(dāng)然你也可以自己寫一些方法,比如 List<User> findByUsername(String username),JPA會自動根據(jù)方法名來創(chuàng)建實現(xiàn)。

測試

package org.schhx.springbootlearn.dao;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.schhx.springbootlearn.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Example;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    @Transactional
    public void create() throws Exception {
        String id = UUID.randomUUID().toString();
        User user = new User().setId(id).setUsername("張三").setAge(20);
        User result = userRepository.save(user);
        System.out.println(result);
        Assert.assertNotEquals(null, result);
    }

    @Test
    @Transactional
    public void findByUserName() throws Exception {
        String id = UUID.randomUUID().toString();
        User user = new User().setId(id).setUsername("張三").setAge(20);
        userRepository.save(user);
        List<User> result = userRepository.findByUsername("張三");
        System.out.println(result);
        Assert.assertNotEquals(null, result);
    }

    @Test
    @Transactional
    public void findByExample() throws Exception {
        String id = UUID.randomUUID().toString();
        User user = new User().setId(id).setUsername("張三").setAge(20);
        userRepository.save(user);
        List<User> result = userRepository.findAll(Example.of(new User().setUsername("張三")));
        System.out.println(result);
        Assert.assertNotEquals(null, result);
    }
}

完整示例

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容