JavaRush /จาวาบล็อก /Random-TH /ฤดูใบไม้ผลิไม่น่ากลัวหรือจะถามคำถามฐานข้อมูลได้อย่างไร
Павел
ระดับ

ฤดูใบไม้ผลิไม่น่ากลัวหรือจะถามคำถามฐานข้อมูลได้อย่างไร

เผยแพร่ในกลุ่ม
เนื้อหาของวงจรของบทความ วันนี้เรากำลังสรุปการทำงานกับฐานข้อมูลซึ่งเป็นส่วนหนึ่งของโครงการของเรา หากคุณทำทุกอย่างถูกต้องแล้ว คุณควรมี 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 ของเรากลับไปที่โฟลเดอร์ทรัพยากร แต่เรายังคงต้องการมัน: 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: line ตรงนั้น (show sql) แล้วเปลี่ยน false เป็นจริง เราเปิดตัวโครงการและดูที่คอนโซล บันทึกจะเต็มไปด้วยรายการใหม่ที่คล้ายคลึงกับ 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 ซึ่งหมายความว่าชายผู้มีความลับคนนี้วางอุ้งเท้าขนปุยไว้ที่นี่ หลังจากอ่านเกี่ยวกับเขาบนอินเทอร์เน็ต เราได้เรียนรู้ว่าคุณไฮเบอร์ กำลังนำแบบจำลอง ORM ไปใช้ โมเดลเชิงวัตถุสัมพันธ์อธิบายความสัมพันธ์ระหว่างวัตถุซอฟต์แวร์และบันทึกในฐานข้อมูล หลังจากแก้ไขแนวคิดนี้แล้ว เรายังคงคิดอย่างมีเหตุผลต่อไป ในด้านหนึ่ง เรามี วัตถุ FruitEntityมันมีสามฟิลด์: รหัสจำนวนเต็ม; ผลไม้สตริงชื่อ; รหัสผู้ให้บริการจำนวนเต็ม ในทางกลับกัน เรามีตารางในฐานข้อมูลFruit_tableพร้อมช่องid_fruit type integer, Fruit_name type varchar(255) , provider_code type integer โดยทั่วไปแล้ว Hibernate จะใช้ วัตถุ FruitEntityดึงค่าของฟิลด์ของวัตถุออกมาและเขียนลงในฟิลด์ตารางที่เกี่ยวข้อง ฉันมีคำถามสำหรับคุณ: ดูสิใน คลาส InitiateUtilsเราได้ดำเนินการเติมตารางผลไม้ แต่ด้วยเหตุผลบางอย่างเราตั้งค่าให้มีเพียงสองฟิลด์ ส่วนที่สามอยู่ที่ไหน
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
ฉันแน่ใจว่าคุณจะคิดออกเอง นอกจากนี้ เราได้พูดคุยสั้น ๆ เกี่ยวกับปัญหานี้ในบทความก่อนหน้าสุดท้าย ขั้นแรก หาว่าช่องไหนไม่อยู่ที่นี่ แล้วคุณจะเข้าใจทุกอย่าง ทำได้ดีมาก Hiber สร้างคำขอมากมายให้เรา แต่เราไม่ได้ตาบอด ลองใช้วิธีเพิ่มเติมจาก อินเทอร์เฟซ JpaRepository<> ในคลาส FruitService กันดีกว่า
//возвращает запись из таблицы по 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 จากนั้นใช้ใน คลาส InitiateUtilsสำหรับFruitEntityและProviderEntityและพิมพ์ผลลัพธ์ไปยังคอนโซล (อย่างไรก็ตาม หากคุณไม่ทราบ คุณสามารถเขียน “System.out.println()” ได้อย่างรวดเร็วโดยพิมพ์ sout แล้วกด Enter สิ่งเดียวกันนี้ใช้ได้กับ “public static void main(String[] args){} ” เพียงพิมพ์ psvm แล้วคุณก็ไป ฯลฯ ) ฉันคิดว่าคุณได้จัดการกับมันแล้วและเราพร้อมที่จะเดินหน้าต่อไป ไปที่ อินเทอร์เฟซ FruitRepositoryและเริ่มพิมพ์ (คือพิมพ์และไม่คัดลอก) วิธีการต่อไปนี้: List<FruitEntity> f คุณควรได้รับสิ่งต่อไปนี้ ฤดูใบไม้ผลิไม่น่ากลัวหรือจะถามคำถามฐานข้อมูลได้อย่างไร - 2 เพียงเรียกวิธีการราวกับว่าคุณกำลังเขียนแบบสอบถาม: findById(Integer id ) - ค้นหาวัตถุด้วย id; countFruitEntityByFruitName(String name) - จะนับจำนวนผลไม้ที่มีชื่อเฉพาะ เหล่านี้เป็นแบบสอบถามที่สร้างโดยชื่อของวิธีการ อย่าลืมอ่านเกี่ยวกับพวกเขาและใช้วิธีการระหว่าง (จำนวนเต็มจาก, จำนวนเต็มถึง) ในคลาส FruitServiceเพื่อค้นหารายการ <FruitEntity> ด้วยค่าของฟิลด์ provider_codeที่รวมอยู่ใน เป็นระยะเวลาหนึ่งและแสดงผลการทำงานในคอนโซล ตัวอย่างเช่น ค้นหาผลไม้ทั้งหมดที่มีหมายเลขซัพพลายเออร์อยู่ระหว่าง 5 ถึง 7 อย่ารีบอ่านเพิ่มเติมจนกว่าคุณจะนำวิธีนี้ไปใช้ เนื่องจากจะใช้เวลาไม่นาน ดังที่คุณอาจได้อ่านในบทความเกี่ยวกับการสืบค้นตามชื่อเมธอด: “คุณไม่สามารถเขียนการสืบค้นทั้งหมดเช่นนี้ได้ แต่สามารถเขียนการสืบค้นแบบธรรมดาได้” สำหรับการสืบค้นที่ซับซ้อนมากขึ้น จะใช้คำอธิบายประกอบ @Query และใช้ JPQLแทน SQL (โปรดจดบันทึกบทความนี้ด้วย) สำหรับโปรเจ็กต์ของเรา คุณสามารถสร้างการสืบค้น JOIN ได้ดังนี้:
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 มาตรฐานจะเป็น: "select Fruit_table.fruit_name, provider_table.provider_name จาก Fruit_table left join provider_table on fruit_table.provider_code = provider_table.id" ที่นี่คุณสามารถสร้างการติดต่อได้อย่างง่ายดาย: f ruit_tableคือFruitEntiy fโดยที่FruitEntiyเป็นประเภทของตัวแปรfคือชื่อของมัน นั่นคือ SQL ทำงานกับตารางและฟิลด์ และ JPQL กับอ็อบเจ็กต์และฟิลด์ของพวกมัน อีกครั้งFruit_table.fruit_nameคือf.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);
        }
เราเปิดตัวโครงการและดูบันทึกใหม่ในคอนโซล: ตารางผลไม้และซัพพลายเออร์ของพวกเขา Fruit1, null Fruit2, ผู้ให้บริการ 5 ผลไม้ 3, ผู้ให้บริการ 2 ผลไม้ 4, ผู้ให้บริการ 5 ผลไม้ 5, null Fruit6, null Fruit7, null Fruit8, null Fruit9, null ตารางผลไม้และของพวกเขา ซัพพลายเออร์ 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 ในคอนโซลแล้ว คุณสามารถคืนค่า false แทนที่ในไฟล์ yaml ได้ เหตุใดตารางแรกจึงมีค่าว่าง คุณจะพบว่าคุณอ่านเกี่ยวกับJOIN SQL หรือ ไม่ ดังนั้นเราจึงดำเนินการค้นหาฐานข้อมูลเสร็จแล้ว ฉันแน่ใจว่าคุณยังมีคำถามมากมาย แต่ฉันหวังว่าคุณจะค้นหาคำตอบสำหรับพวกเขา ฉันพยายามเน้นเส้นทางการค้นหา เรามาลองสรุปทุกสิ่งที่เราได้เรียนรู้ในช่วงเวลานี้: 1. คุณสามารถรันเว็บเซิร์ฟเวอร์ใน Spring ได้และก็ไม่ยาก 2. เพื่อทำความเข้าใจว่ามันทำงานอย่างไร คุณต้องศึกษาทฤษฎีก่อน เกี่ยวกับหนังสือ บทความเกี่ยวกับสปริง บทความเกี่ยวกับสิ่งที่มีประโยชน์ 3. เพื่อให้เข้าใจในการเปลี่ยนเป็นโค้ดจริง คุณต้องเขียนโค้ด และก่อนที่จะดำเนินการต่อ ให้ลงมือทำโปรเจ็กต์ง่ายๆ บน spring-boot และเป็นการดีกว่าที่จะไม่คัดลอกโค้ดที่เขียน แต่ควรเขียนใหม่ ฉันจะโพสต์โครงการที่คุณและฉันกำลังทำอยู่ที่นี่ แต่ฉันจะขึ้นอยู่กับการรับรู้ของคุณ และฉันมั่นใจว่าคุณจะไม่คัดลอกและวางโดยไร้เหตุผล ลิงก์ไปยัง ที่เก็บ git clone https://FromJava@bitbucket.org/FromJava/jd.git สำหรับผู้ที่ไม่ทราบวิธีใช้ลิงก์นี้ ฉันขอแนะนำให้ใช้สองโครงการฝึกอบรม: โครงการเกี่ยวกับการพ่นสีรถยนต์: ชั้นหนึ่ง: CarEntity{ จำนวนเต็ม รหัส; สตริงชื่อโมเดล; สีสาย; } คลาสที่สอง: ColorEntity{ รหัสจำนวนเต็ม; สีสาย; ราคาจำนวนเต็ม; } กรอกฐานข้อมูล (คิดชื่อที่สมจริงเพื่อให้เข้าใจได้ง่ายขึ้น) ใช้งาน: , เอนทิตี, ที่เก็บข้อมูล, บริการ, สร้างแบบสอบถามมาตรฐานและแบบข้ามตาราง (การทาสี BMW สีแดงราคาเท่าไหร่ สีอะไร แพงที่สุด เขียนโมเดลบนคอนโซลตามลำดับตัวอักษรและอื่น ๆ ); โครงการห้องสมุด: ชั้นหนึ่ง: BookEntity{ Integer id; ชื่อสตริงBook; จำนวนเต็มปีสร้าง; จำนวนเต็ม autorId; } คลาสที่สอง: AutorEntity{ รหัสจำนวนเต็ม; สตริง firstNameAutor; สตริงนามสกุล Autor; } กรอกฐานข้อมูล (คิดชื่อตามความเป็นจริงเพื่อให้เข้าใจได้ง่ายขึ้น) นำไปใช้: เอนทิตี พื้นที่เก็บข้อมูล บริการ สร้างแบบสอบถามมาตรฐานและระหว่างตาราง (ใครเขียนหนังสือเล่มไหน หนังสือเล่มไหนเขียนก่อน หนังสือเล่มไหนเขียน ตั้งแต่ปี 1800 ถึง 1900 ผู้เขียนคนไหนเขียนหนังสือมากที่สุด); ตัวอย่างการกรอก ฐานข้อมูลโครงการ "ห้องสมุด" ตารางหนังสือ BookEntity(id=1, nameBook=Woe from Wit, yearCreat=1824, authorId=1) BookEntity(id=2, nameBook=War and Peace, 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=Griboyedov) AuthorEntity(id=2 , firstNameAuthor=Lev, LastNameAuthor=Tolstoy) AuthorEntity(id=3, firstNameAuthor=Mikhail, LastNameAuthor=Lermontov) AuthorEntity(id=4, firstNameAuthor=Alexander, LastNameAuthor=Pushkin) ขอให้ ทุกคนโชคดีแล้วพบกันใหม่!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION