【SpringBoot】SpringBoot整合Spring Data JPA 使用JPA操作MySQL數據庫

SpringBoot整合Spring Data JPA

使用JPA操作數據庫

JPA是Java Persistence API的簡稱,是JCP組織發佈的Java EE標準之一。JPA是一種面向對象的查詢語言,定義了獨特的JPQL(Java Persistence Query Language),是一種針對實體的查詢語言,無論是查詢還是修改,全部操作的都是對象實體,而非數據庫的表。

添加Spring Data JPA的起步依賴

JPA依賴配置

新建項目,在pom文件中加入JPA依賴

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

添加數據庫驅動依賴

在pom文件中加入MySQL依賴

<!-- MySQL連接驅動 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

在application.properties中配置數據庫和jpa的相關屬性

在配置文件中加入數據庫配置

JPA的基本配置介紹

  • validate:在加載hibernate時,驗證創建數據庫表結構。
  • create:每次加載hibernate,重新創建數據庫表結構,設置時要注意,如果設置錯誤的話,就會造成數據的丟失。
  • create-drop:在加載的時候創建表,在關閉項目時刪除表結構。
  • update:加載時更新表結構。
  • none:加載時不做任何操作。
  • spring.jpa.show-sql配置 設置爲true時,可以在控制檯打印SQL。

application.properties

#DB Configuration:
#數據庫配置

#數據庫驅動
spring.datasource.driverClassName=com.mysql.jdbc.Driver
#數據庫地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
#數據庫用戶名
spring.datasource.username=root
#數據庫密碼
spring.datasource.password=123456

#JPA Configuration:
#JPA 配置


spring.jpa.database=MySQL
#控制檯打印SQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy

問題:

Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

application.properties要改

#DB Configuration:
#數據庫配置

#數據庫驅動
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#數據庫地址
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
#數據庫用戶名
spring.datasource.username=root
#數據庫密碼
spring.datasource.password=123456

#JPA Configuration:
#JPA 配置


spring.jpa.database=MySQL
#控制檯打印SQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy

com.mysql.jdbc.Driver 高版本使用 com.mysql.cj.jdbc.Driver

創建實體配置實體

創建一個實體對象,在類上加入註解@Entity來表明這是一個實體類,

在屬性上使用@Id表明這是數據庫中的主鍵ID,使用@GeneratedValue(strategy = GenerationType.IDENTITY)表明此字段自增長,在屬性上加入@Column(nullable = false,unique = true)可以設置字段的一些屬性,比如nullable爲非空、unique唯一約束,還提供了其他屬性等等。

User.java

package cn.liuawen.domain;

import lombok.Data;

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

@Entity
@Data
public class User {
    // 主鍵
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // 用戶名
    private String username;
    // 密碼
    private String password;
}

編寫UserRepository

創建數據操作層

新建一個repository接口,使其繼承JpaRepository,這個接口默認提供一組與JPA規範相關的方法

UserRepository.java

package cn.liuawen.repository;

import cn.liuawen.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;


//實體、類型
public interface UserRepository  extends JpaRepository<User,Long> {
    public List<User> findAll();
}

來分析一波

UserRepository 繼承 JpaRepository<User,Long> 那JpaRepository<T, ID>是什麼

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.jpa.repository;

import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, 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> S saveAndFlush(S var1);

    void deleteInBatch(Iterable<T> var1);

    void deleteAllInBatch();

    T getOne(ID var1);

    <S extends T> List<S> findAll(Example<S> var1);

    <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

從源代碼中可以看到,默認爲我們提供了很多簡單的方法,如findAll()、getOne()等,而JpaRepository則繼承了PagingAndSortingRepository接口。PagingAndSortingRepository接口代碼其代碼如下所示。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
    Iterable<T> findAll(Sort var1);

    Page<T> findAll(Pageable var1);
}

PagingAndSortingRepository接口繼承了CrudRepository接口,實現了有關分頁排序等相關的方法,其代碼如下所示。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.repository;

import java.util.Optional;

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S var1);

    <S extends T> Iterable<S> saveAll(Iterable<S> var1);

    Optional<T> findById(ID var1);

    boolean existsById(ID var1);

    Iterable<T> findAll();

    Iterable<T> findAllById(Iterable<ID> var1);

    long count();

    void deleteById(ID var1);

    void delete(T var1);

    void deleteAll(Iterable<? extends T> var1);

    void deleteAll();
}

CrudRepository接口繼承了Spring Data JPA的核心接口Repository,實現了有關CRUD相關的方法(增、刪、改、查)。在Repository接口中沒有提供任何方法,僅僅作爲一個標識來讓其他類實現它作爲倉庫接口類,其代碼如代碼所示。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.data.repository;

import org.springframework.stereotype.Indexed;

@Indexed
public interface Repository<T, ID> {
}

除了Repository接口以外,其餘接口都含有一個@NoRepositoryBean註解,加入這個註解的類,Spring就不會實例化,用作父類的Repository。

編寫測試類

簡單測試運行

package cn.liuawen;

import cn.liuawen.domain.User;
import cn.liuawen.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootJpaApplication.class)
public class JpaTest {
    @Autowired
    private UserRepository userRepository;

    @Test
    public void test1(){
        List<User> users = userRepository.findAll();
        System.out.println(users);
    }
}

在使用JPA操作數據庫時,操作特別簡單,基本上使用Repository提供的幾個方法已經可以滿足我們的需求。

滿足不了自己寫SQL咯

Error

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-06-16 01:19:02.111 ERROR 18708 --- [           main] o.s.boot.SpringApplication               : Application run failed

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: 

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: 
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.Driver
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	a



Caused by: java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.Driver
	at org.springframework.util.Assert.state(Assert.java:94) ~[spring-core-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	

我沒加MySQL的驅動

<!-- MySQL連接驅動 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Loading class com.mysql.jdbc.Driver'. This is deprecated. The new driver class iscom.mysql.cj.jdbc.Driver’. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

高版本是 com.mysql.cj.jdbc.Driver

控制檯打印信息

在這裏插入圖片描述

Hibernate: select user0_.id as id1_0_, user0_.password as password2_0_, user0_.username as username3_0_ from user user0_
[User(id=1, username=菜雞文, password=123), User(id=2, username=柳小子, password=123)]

參考資料

簡單記錄

1、Spring實戰(第5版)作者:[美]克雷格·沃斯譯者:張衛濱

2、Spring Boot 2實戰之旅/楊洋著

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