JavaRush /Java Blog /Random-TW /Spring並不可怕,還是如何問資料庫問題
Павел
等級 11

Spring並不可怕,還是如何問資料庫問題

在 Random-TW 群組發布
文章週期的內容 今天,作為我們專案的一部分,我們正在完成資料庫的工作。如果你做的一切正確,那麼你應該有一個具有以下依賴項的 pom:
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <java.version>1.8</java.version>
</properties>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath/><!-- lookup parent from repository -->
</parent>
<dependencies>
    <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>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
這就是該專案的結構: Spring並不可怕,還是如何問資料庫問題 - 1 你知道我們已經很久沒有記住誰了嗎?這是application.yml,我們在之前的一篇文章中沒有過多談論它。現在讓我們繼續刪除它!是的,是的,刪除就是這樣!如果我們現在啟動該項目,一切都會像以前一樣工作,試試這個。發生這種情況是因為 Spring 本身配置了預設設定。現在我們需要將 yml 檔案返回 resources 資料夾,我們仍然需要它:application.yml(名稱應該相同)
spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:test;
    username: sa
    password:
    h2:
      console:
        enabled: true
  jpa:
    hibernate.ddl-auto: create
    generate-ddl: true
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
上次,我們使用 JpaRepository<> 介面的方法實作了對資料庫的多次查詢:
//сохранить одну запись в таблицу фруктов
public void save(FruitEntity fruitEntity){
    fruitRepository.save(fruitEntity);
}
//получить все записи из таблицы фруктов
public List<FruitEntity> getAll(){
   return fruitRepository.findAll();
}
//сохранить несколько записей в таблицу фруктов
public void saveAll(List<FruitEntity> fruits){
    fruitRepository.saveAll(fruits);
}
如果您像我上次要求您一樣閱讀有關SQL 的內容,那麼您應該知道此類資料庫操作必須使用 SQL 查詢來執行。但專案中沒有任何暗示;即使在控制台日誌中也沒有類似的內容。讓我們找到它們,打開 application.yml,找到 show-sql: 行(show sql)並將 false 更改為 true。我們啟動項目,看一下控制台,日誌中充滿了與SQL非常相似的新條目,實際上,其中大部分並不難理解,例如:
Hibernate: drop table fruit_table if exists //удалить таблицу fruit_table  если она есть
Hibernate: drop table provider_table if exists
Hibernate: create table fruit_table (id_fruit integer not null, fruit_name varchar(255), provider_code integer, primary key (id_fruit))//создать таблицу fruit_table с полями id_fruit тип integer not null, fruit_name  тип varchar(255), provider_code тип integer, назначить первичным ключем поле id_fruit
Hibernate: create table provider_table (id_provider integer not null, provider_name varchar(255), primary key (id_provider))
但這個條目可能會因為它的問號而引起很多疑問:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
讓我們邏輯思考一下:首先,我們看到Hibernate這個詞,這意味著這個神秘的傢伙把他毛茸茸的爪子放在這裡了。在網路上了解了他的相關資訊後,我們了解到Hiber先生 是 ORM 模型的實現。物件關係模型描述了軟體物件和資料庫中的記錄之間的關係。固定了這個想法,我們繼續邏輯思考:一方面,我們有一個FruitEntity對象,它有三個欄位:Integer id;字符串水果名稱;整數提供者代碼。 另一方面,我們在資料庫Fruit_table中有一個表,其中字段id_fruit類型為整數 fruit_name 類型為varchar(255)provider_code類型為整數。 粗略地說,Hibernate 獲取一個FruitEntity對象,提取該對象字段的值並將它們寫入相應的表字段。我有一個問題想問你:你看,在InitiateUtils類中我們實現了填充水果表,但由於某種原因我們只將值設置為兩個字段,第三個字段在哪裡?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
我相信您會自己弄清楚這一點,此外,我們在上一篇文章中簡要討論了這個問題。先弄清楚哪個欄位不在這裡,然後你就明白了一切。好吧,幹得好,Hiber 為我們產生了一堆請求。但我們不是盲目,讓我們在FruitService類別中的JpaRepository<>介面中再實作一些方法
//возвращает запись из таблицы по id
public Optional<FruitEntity> getById(Integer id){
   return fruitRepository.findById(id);
}

//удаляет запись из таблицы по id
public void delById(Integer id){
    fruitRepository.deleteById(id);
}

//возвращает true or false при поиске в таблице Фруктов an object который соответствует типу FruitEntity or принадлежит к типу an object который наследуется от FruitEntity
public Boolean exist(Example<? extends FruitEntity> example){
    return fruitRepository.exists(example);
}
在 ProviderService 類別中實作相同的方法。然後在FruitEntityProviderEntityInitiateUtils類別中使用它們,並將結果列印到控制台。(順便說一句,如果您不知道,您可以透過輸入sout 並按Enter 鍵來快速編寫“System.out.println()”,同樣的操作也適用於“public static void main(String[] args){ }” “只需輸入 psvm 即可,等等)。我認為您已經解決了這個問題,我們已準備好繼續前進。讓我們轉到FruitRepository介面並開始在其中鍵入(即鍵入而不是複製)以下方法: List<FruitEntity> f 您應該得到以下內容。 只需像編寫查詢一樣調用該方法: findById(Integer id ) - 透過 id查找對象;countFruitEntityByFruitName(String name) - 將計算具有特定名稱的水果的數量;這些是由方法名稱產生的查詢; 請務必閱讀它們並在FruitService類別中實作Between(Integer from, Integer to)方法,以透過包含在中的的值搜尋List<FruitEntity>provider_code 例如:找到所有供應商編號在 5 到 7 之間的水果。在實現方法之前先不要急於繼續閱讀,不會花很長時間。正如您可能在有關按方法名稱查詢的文章中讀到的那樣:“您不能像這樣編寫所有查詢,但可以編寫簡單的查詢。” 對於更複雜的查詢,請使用@Query註解,並使用JPQL代替SQL (也請注意這篇文章),對於我們的項目,您可以進行JOIN查詢,如下所示: Spring並不可怕,還是如何問資料庫問題 - 2
package ru.java.rush.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import ru.java.rush.entities.FruitEntity;

import java.util.List;

@Repository
public interface FruitRepository extends JpaRepository<FruitEntity,Integer> {

    @Query("select f.fruitName, p.providerName from  FruitEntity f left join ProviderEntity p on f.providerCode = p.id")
    List<String> joinSting();

}
標準 SQL 查詢為: “selectfruit_table.fruit_name,provider_table.provider_name fromfruit_table left joinprovider_table onfruit_table.provider_code =provider_table.id”。 這裡可以很容易地建立對應關係:f ruit_tableFruitEntiy f,其中FruitEntiy是變數的類型,f是變數的名稱,即 SQL 處理表和字段,而 JPQL 處理物件及其字段。同樣,fruit_table.fruit_namef.fruitName;由於我們使用對象,因此我們可以輸出對象:讓我們寫另一個 FruitRepository 方法
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
讓我們在 FruitService 類別中實作這兩個方法
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
聽起來不錯,但他們仍然使用舊的 SQL 來進行複雜的查詢
@Query(
        value = "select fruit_table.fruit_name, provider_table.provider_name from  fruit_table  join provider_table on fruit_table.provider_code = provider_table.id_provider",  //по идее эту портянку надо засунуть в Howой нибудь  Enum
        nativeQuery = true) //нужно только пометить только nativeQuery = true
ListList<String> joinSqlFruit();
我們在InitiateUtils類別中使用它們
System.out.println("\nТаблица фруктов и их поставщиков");
for (String join : fruitService.joinString()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
for (FruitEntity join : fruitService.joinFruit()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
        for (String join : fruitService.joinSqlFruit()) {
            System.out.println(join);
        }
我們啟動該項目,並在控制台中看到新日誌: Table offruits and their sellers Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,nullull Fruit8,null Fruits,9,null Fruit Fruit,null Fruit供應商FruitEntity(id= 2,fruitName=Fruit2,providerCode=5) FruitEntity(id=3,fruitName=Fruit3,providerCode=2) FruitEntity(id=4,fruitName=Fruit4,providerCode=5) 水果及其供應商表Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 是的,如果你已經厭倦了控制台中的「偽」和只是 SQL 查詢,你可以在 yaml 檔案中的位置返回 false。為什麼第一個表中有null,如果你有讀過JOIN SQL就會發現。這樣,我們就完成了對資料庫的查詢,我相信您仍然有很多問題,但我希望您能找到這些問題的答案,我試圖突出顯示搜尋路徑。讓我們試著總結一下我們這段時間所學到的一切: 1. 您可以在 Spring 中運行 Web 伺服器,這並不困難。2. 要了解這一切是如何運作的,您需要深入研究理論。 關於這本書 關於 spring 的 文章 關於有用的東西的 文章 3. 為了將理解轉化為物理代碼,您需要編寫代碼,在繼續之前,先了解一下 spring-boot 上的簡單項目。而且最好不要複製寫好的程式碼,而是重寫它。我將在這裡發布你和我一直在做的項目,但我將依靠你的意識,我相信你不會盲目地複製貼上。 連結到 git 克隆儲存庫 https://FromJava@bitbucket.org/FromJava/jd.git 對於那些不知道如何使用此連結的人, 我建議實施兩個培訓專案: 關於噴漆汽車的專案: 第一類: CarEntity{ Integer ID; 字串模型名稱;字串顏色;第二 類: ColorEntity{ Integer id; 字串顏色;整數價格;填充 資料庫(起一個現實的名字,這樣會更容易理解),實現:,實體,存儲庫,服務,創建標準和跨表查詢(把一輛寶馬漆成紅色需要多少錢?什麼顏色最貴的?按字母順序將模型寫入控制台等); 圖書館項目: 第一類: BookEntity{ Integer id; 字串名稱Book;整數年份創建;整數 autord;第二 類: AutorEntity{ Integer id; 字串firstNameAutor;字符串姓氏Autor;填充 資料庫(起一個現實的名字,這樣會更容易理解),實現:實體,儲存庫,服務,創建標準和表間查詢(誰寫了哪本書?哪本書先寫的?哪本書寫的從1800 年到1900 年?哪位作家寫的書最多?);「Library」專案資料庫填寫範例 圖書表 BookEntity(id=1, nameBook=Woe from Wit,yearCreat=1824,authorId=1) BookEntity(id=2,nameBook=戰爭與和平,yearCreat=1863,authorId=2) BookEntity(id=3,nameBook= Mtsyri,yearCreat = 1838,authorId = 3)BookEntity(id = 4,nameBook = Eugene Onegin,yearCreat = 1833,authorId = 4)作者表AuthorEntity(id = 1,firstNameAuthor = Alexander,lastNameAuthor = Ented(id = Entority) ) ,firstNameAuthor=Lev,lastNameAuthor=Tolstoy)AuthorEntity(id=3,firstNameAuthor=Mikhail,lastNameAuthor=Lermontov)AuthorEntity(id=4,firstNameAuthor=Alexander,lastNameAuthor=PushkindAuthor= Pushkind
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION