JavaRush /Blog Java /Random-MS /Musim bunga tidak menakutkan, atau bagaimana untuk bertan...

Musim bunga tidak menakutkan, atau bagaimana untuk bertanya soalan pangkalan data

Diterbitkan dalam kumpulan
KANDUNGAN KITARAN ARTIKEL Hari ini kami sedang memuktamadkan kerja dengan pangkalan data sebagai sebahagian daripada projek kami. Jika anda melakukan semuanya dengan betul, maka anda harus mempunyai pom dengan kebergantungan berikut:
<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>
Dan inilah struktur projek: Musim bunga tidak menakutkan, atau bagaimana untuk bertanya soalan pangkalan data - 1 Adakah anda tahu siapa yang kami tidak ingat untuk masa yang lama? Ini adalah application.yml, kami tidak banyak bercakap mengenainya dalam salah satu artikel sebelumnya. Sekarang mari kita teruskan dan padamkannya! Ya, ya padam dan itu sahaja! Jika kami melancarkan projek sekarang, semuanya akan berfungsi seperti dahulu, cuba ini. Ini berlaku kerana Spring itu sendiri telah dikonfigurasikan dengan tetapan lalai. Sekarang kami perlu mengembalikan fail yml kami ke folder sumber, kami masih memerlukannya: application.yml (namanya mestilah sama)
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
Kali terakhir, kami melaksanakan beberapa pertanyaan ke pangkalan data menggunakan kaedah antara muka 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);
}
Jika anda membaca tentang SQL , seperti yang saya minta anda lakukan kali terakhir, maka anda harus tahu bahawa tindakan sedemikian dengan pangkalan data mesti dilakukan menggunakan pertanyaan SQL. Tetapi tidak ada petunjuk tentang ini dalam projek; walaupun dalam log konsol tidak ada yang serupa. Mari cari mereka, buka application.yml, cari baris show-sql: di sana (tunjukkan sql) dan tukar palsu kepada benar. Kami melancarkan projek dan melihat konsol, log diisi dengan entri baru yang hampir sama dengan SQL, sebenarnya, kebanyakannya tidak sukar untuk difahami, contohnya:
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))
Tetapi entri ini mungkin menimbulkan banyak persoalan kerana tanda tanyanya:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Mari kita fikir secara logik: Pertama, kita melihat perkataan Hibernate, yang bermaksud lelaki perahsia ini telah meletakkan kaki berbulunya di sini. Selepas membaca tentang beliau di Internet, kami mengetahui bahawa Encik Hiber adalah pelaksanaan model ORM. Model hubungan objek menerangkan hubungan antara objek perisian dan rekod dalam pangkalan data. Setelah membetulkan idea ini, kami terus berfikir secara logik: Di satu pihak, kami mempunyai objek FruitEntity , ia mempunyai tiga medan: Integer id; Nama buah rentetan; Kod pembekal integer. Sebaliknya, kami mempunyai jadual dalam pangkalan data fruit_table dengan medan id_fruit type integer, fruit_name type varchar(255) , provider_code type integer. Secara kasarnya, Hibernate mengambil objek FruitEntity , mengeluarkan nilai medan objek dan menulisnya ke medan jadual yang sepadan. Saya ada soalan untuk anda: Lihat, dalam kelas InitiateUtils kami melaksanakan pengisian jadual buah, tetapi atas sebab tertentu kami menetapkan nilai kepada dua medan sahaja, di manakah yang ketiga?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Saya pasti anda akan memikirkannya sendiri, selain itu, kami telah menyentuh secara ringkas tentang isu ini dalam artikel sebelum yang terakhir. Mula-mula, tentukan bidang mana yang tidak ada di sini, dan kemudian anda akan memahami segala-galanya. Syabas, Hiber menjana banyak permintaan untuk kami. Tetapi kami tidak buta, mari laksanakan beberapa kaedah lagi daripada antara muka JpaRepository<> dalam kelas 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);
}
Laksanakan kaedah yang sama dalam kelas ProviderService. Kemudian gunakannya dalam kelas InitiateUtils untuk FruitEntity dan ProviderEntity dan cetak hasilnya ke konsol. (Dengan cara ini, jika anda tidak tahu, anda boleh menulis “System.out.println()” dengan cepat dengan menaip sout dan menekan enter, perkara yang sama berfungsi dengan “public static void main(String[] args){} ” hanya taip psvm dan begitulah seterusnya ) . Saya fikir anda telah menanganinya dan kami bersedia untuk meneruskan. Mari pergi ke antara muka FruitRepository dan mula menaip di dalamnya (iaitu menaip dan tidak menyalin) kaedah berikut: Senarai<FruitEntity> f Anda sepatutnya mendapat perkara berikut. Musim bunga tidak menakutkan, atau bagaimana untuk bertanya soalan pangkalan data - 2 Hanya panggil kaedah seolah-olah anda sedang mengarang pertanyaan: findById(Integer id ) - mencari objek dengan id; countFruitEntityByFruitName(String name) - akan mengira bilangan buah dengan nama tertentu; Ini adalah pertanyaan yang dijana dengan nama kaedah; pastikan anda membaca tentangnya dan melaksanakan kaedah antara (Integer dari, Integer ke) dalam kelas FruitService untuk mencari Senarai<FruitEntity> mengikut nilai medan provider_code yang disertakan dalam selang waktu tertentu, dan paparkan hasil kerja dalam konsol. Contohnya: cari semua buah-buahan yang nombor pembekalnya antara 5 dan 7. Jangan tergesa-gesa membaca lebih lanjut sehingga anda melaksanakan kaedah itu, ia tidak akan mengambil masa yang lama. Seperti yang anda mungkin pernah baca dalam artikel tentang pertanyaan mengikut nama kaedah: "Anda tidak boleh menulis semua pertanyaan seperti ini, tetapi yang mudah boleh ditulis." Untuk pertanyaan yang lebih kompleks, anotasi @Query digunakan dan JPQL digunakan dan bukannya SQL (juga ambil perhatian artikel ini). Untuk projek kami, anda boleh membuat pertanyaan JOIN, seperti ini:
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();

}
Pertanyaan SQL standard ialah: "pilih fruit_table.fruit_name, provider_table.provider_name daripada fruit_table kiri sertai provider_table pada fruit_table.provider_code = provider_table.id". Di sini anda boleh membuat surat-menyurat dengan mudah: f ruit_table ialah FruitEntiy f, dengan FruitEntiy ialah jenis pembolehubah, f ialah namanya, iaitu, SQL berfungsi dengan jadual dan medan, dan JPQL dengan objek dan medannya. Sekali lagi fruit_table.fruit_name ialah f.fruitName ; Oleh kerana kita bekerja dengan objek, kita boleh mengeluarkan objek: Mari tulis kaedah FruitRepository yang lain
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Mari kita laksanakan kedua-dua kaedah dalam kelas FruitService
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
Kedengarannya tidak buruk, tetapi mereka masih menggunakan SQL lama yang baik untuk pertanyaan kompleks
@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();
Dan kami menggunakan kesemuanya dalam kelas 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);
        }
Kami melancarkan projek dan melihat log baharu dalam konsol: Jadual buah-buahan dan pembekalnya Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Null Table of fruits and their pembekal FruitEntity(id= 2, fruitName=Fruit2, providerCode=5) FruitEntity(id=3, fruitName=Fruit3, providerCode=2) FruitEntity(id=4, fruitName=Fruit4, providerCode=5) Jadual buah-buahan dan pembekalnya Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Ya, jika anda sudah bosan dengan "pseudo" dan hanya pertanyaan SQL dalam konsol, anda boleh mengembalikan palsu sebagai gantinya dalam fail yaml. Mengapa terdapat null dalam jadual pertama, anda akan mengetahui jika anda membaca tentang JOIN SQL . Oleh itu, kami selesai dengan pertanyaan kepada pangkalan data, saya pasti bahawa anda masih mempunyai banyak soalan, tetapi saya berharap anda akan mencari jawapan kepada mereka, saya cuba menyerlahkan laluan carian. Mari cuba ringkaskan semua yang telah kami pelajari pada masa ini: 1. Anda boleh menjalankan pelayan web dalam Spring dan ia tidak sukar. 2. Untuk memahami bagaimana semuanya berfungsi, anda perlu menyelami teori. Mengenai buku Artikel tentang musim bunga Artikel tentang perkara yang berguna 3. Untuk memahami menjadi kod fizikal, anda perlu kod, dan sebelum meneruskan, dapatkan projek mudah pada spring-boot. Dan lebih baik tidak menyalin kod bertulis, tetapi menulis semula. Saya akan menyiarkan projek yang anda dan saya telah kerjakan di sini, tetapi saya akan bergantung pada kesedaran anda dan saya pasti anda tidak akan menyalin-tampal secara sembarangan. Pautan ke repositori klon git https://FromJava@bitbucket.org/FromJava/jd.git Bagi mereka yang tidak tahu cara menggunakan pautan ini, saya cadangkan untuk melaksanakan dua projek latihan: Projek tentang mengecat kereta: Kelas pertama: CarEntity{ Integer ID; String modelName; Warna rentetan; } Kelas kedua: ColorEntity{ Integer id; Warna rentetan; harga integer; } Isikan pangkalan data (hasilkan nama yang realistik supaya lebih mudah difahami), laksanakan: , entiti, repositori, perkhidmatan, buat pertanyaan standard dan silang jadual (Berapa kos untuk mengecat BMW merah? Warna apa yang paling mahal? Tulis model ke konsol dalam susunan abjad dan lain-lain); Projek perpustakaan: Kelas pertama: BookEntity{ Integer id; Buku nama rentetan; Integer yearCreat; Integer autoId; } Kelas kedua: AutorEntity{ Integer id; String firstNameAutor; Rentetan lastNameAutor; } Isikan pangkalan data (hasilkan nama yang realistik supaya lebih mudah difahami), laksanakan: entiti, repositori, perkhidmatan, buat pertanyaan standard dan antara jadual (Siapa yang menulis buku mana? Buku mana yang ditulis dahulu? Buku mana yang ditulis dari 1800 hingga 1900? Pengarang manakah yang paling banyak menulis buku?); Contoh untuk mengisi pangkalan data projek "Perpustakaan". Jadual buku 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) Author table 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) Semoga berjaya semua, jumpa lagi!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION