JavaRush /Java Blog /Random-ID /Musim semi tidak menakutkan, atau bagaimana cara mengajuk...
Павел
Level 11

Musim semi tidak menakutkan, atau bagaimana cara mengajukan pertanyaan database

Dipublikasikan di grup Random-ID
ISI SIKLUS ARTIKEL Hari ini kami sedang menyelesaikan pekerjaan dengan database sebagai bagian dari proyek kami. Jika Anda melakukan semuanya dengan benar, maka Anda akan memiliki pom dengan dependensi 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 proyeknya: Musim semi tidak menakutkan, atau bagaimana cara mengajukan pertanyaan database - 1 Tahukah Anda siapa yang sudah lama tidak kita ingat? Ini adalah application.yml, kami tidak banyak membicarakannya di salah satu artikel sebelumnya. Sekarang mari kita lanjutkan dan hapus! Ya, ya, hapus dan selesai! Jika kami meluncurkan proyek sekarang, semuanya akan berfungsi seperti sebelumnya, coba ini. Hal ini terjadi karena Spring sendiri dikonfigurasi dengan pengaturan default. Sekarang kita perlu mengembalikan file yml kita ke folder sumber daya, kita masih membutuhkannya: application.yml (namanya harus 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
Terakhir kali, kami mengimplementasikan beberapa query ke database menggunakan metode antarmuka 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 terakhir kali, maka Anda harus tahu bahwa tindakan dengan database tersebut harus dilakukan menggunakan kueri SQL. Namun tidak ada petunjuk mengenai hal ini di proyek; bahkan di log konsol pun tidak ada hal serupa. Mari kita temukan, buka application.yml, temukan baris show-sql: di sana (show sql) dan ubah false menjadi true. Kami meluncurkan proyek dan melihat konsol, log diisi dengan entri baru yang sangat mirip dengan SQL, sebenarnya kebanyakan tidak sulit untuk dipahami, misalnya:
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))
Namun entri ini mungkin menimbulkan banyak pertanyaan karena tanda tanyanya:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Mari kita berpikir secara logis: Pertama, kita melihat kata Hibernate, yang berarti pria penuh rahasia ini telah meletakkan cakarnya yang berbulu di sini. Setelah membaca tentang dia di Internet, kita mengetahui bahwa Mr. Hiber adalah implementasi model ORM. Model objek-relasional menggambarkan hubungan antara objek perangkat lunak dan catatan dalam database. Setelah memperbaiki gagasan ini, kami terus berpikir secara logis: Di satu sisi, kami memiliki objek FruitEntity , yang memiliki tiga bidang: Integer id; Nama buah tali; Kode penyedia bilangan bulat. Di sisi lain, kami memiliki tabel di database buah_tabel dengan bidang id_buah tipe bilangan bulat, nama_buah tipe varchar(255) , penyedia_kode tipe bilangan bulat. Secara kasar, Hibernate mengambil objek FruitEntity , mengeluarkan nilai bidang objek dan menuliskannya ke bidang tabel yang sesuai. Saya punya pertanyaan untuk Anda: Lihat, di kelas InitiateUtils kami menerapkan pengisian tabel buah, tetapi untuk beberapa alasan kami menetapkan nilainya hanya ke dua bidang, di mana yang ketiga?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Saya yakin Anda akan mengetahuinya sendiri, selain itu, kami telah menyinggung secara singkat masalah ini di artikel sebelumnya. Pertama, cari tahu bidang mana yang tidak ada di sini, dan kemudian Anda akan memahami semuanya. Bagus sekali, Hiber membuat banyak permintaan untuk kami. Namun kita tidak buta, mari kita implementasikan beberapa metode lagi dari antarmuka JpaRepository<> di 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);
}
Terapkan metode yang sama di kelas ProviderService. Kemudian gunakan keduanya di kelas InitiateUtils untuk FruitEntity dan ProviderEntity dan cetak hasilnya ke konsol. (Omong-omong, jika Anda tidak mengetahuinya, Anda bisa dengan cepat menulis “System.out.println()” dengan mengetikkan sout dan menekan enter, hal yang sama juga dapat dilakukan dengan “public static void main(String[] args){} ” cukup ketik psvm dan ini dia, dll. ). Saya pikir Anda sudah mengatasinya dan kami siap untuk melanjutkan. Mari kita pergi ke antarmuka FruitRepository dan mulai mengetik di dalamnya (yaitu mengetik dan tidak menyalin) metode berikut: List<FruitEntity> f Anda akan mendapatkan hal berikut, Musim semi tidak menakutkan, atau bagaimana cara mengajukan pertanyaan database - 2 panggil saja metode tersebut seolah-olah Anda sedang membuat kueri: findById(Integer id ) - menemukan objek berdasarkan id; countFruitEntityByFruitName(String name) - akan menghitung jumlah buah dengan nama tertentu; Ini adalah kueri yang dihasilkan berdasarkan nama metode; pastikan untuk membacanya dan mengimplementasikan metode antara (Bilangan bulat dari, Integer ke) di kelas FruitService untuk mencari Daftar<FruitEntity> berdasarkan nilai bidang kode_penyedia yang disertakan dalam interval tertentu, dan menampilkan hasil pekerjaan di konsol. Misal: cari semua buah-buahan yang nomor pemasoknya antara 5 sampai 7. Jangan terburu-buru membaca lebih lanjut sampai Anda menerapkan caranya, tidak akan memakan waktu lama. Seperti yang mungkin telah Anda baca di artikel tentang kueri berdasarkan nama metode: “Anda tidak dapat menulis semua kueri seperti ini, tetapi kueri sederhana dapat ditulis.” Untuk kueri yang lebih kompleks, anotasi @Query digunakan dan JPQL digunakan sebagai pengganti SQL (perhatikan juga artikel ini). Untuk proyek kami, Anda dapat membuat kueri GABUNG, 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();

}
Kueri SQL standar adalah: "pilih tabel_buah.nama_buah, nama_tabel_penyedia.nama_penyedia dari tabel_buah kiri, gabung tabel_penyedia pada tabel_buah.kode_penyedia = penyedia_tabel.id". Di sini Anda dapat dengan mudah membuat korespondensi: f ruit_table adalah FruitEntiy f, di mana FruitEntiy adalah jenis variabel, f adalah namanya, yaitu SQL bekerja dengan tabel dan bidang, dan JPQL dengan objek dan bidangnya. Sekali lagi Fruit_table.fruit_name adalah f.fruitName ; Karena kita bekerja dengan objek, kita dapat menampilkan objek tersebut: Mari kita tulis metode FruitRepository yang lain
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Mari kita implementasikan kedua metode tersebut di 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 bagus untuk kueri yang 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 semuanya di 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 meluncurkan proyek dan melihat log baru di konsol: Tabel buah-buahan dan pemasoknya Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Tabel buah-buahan dan isinya pemasok FruitEntity(id= 2, FruitName=Fruit2, ProviderCode=5) FruitEntity(id=3, FruitName=Fruit3, ProviderCode=2) FruitEntity(id=4, FruitName=Fruit4, ProviderCode=5) Tabel buah-buahan dan pemasoknya Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Ya, jika Anda sudah bosan dengan "pseudo" dan hanya kueri SQL di konsol, Anda dapat mengembalikan false sebagai gantinya di file yaml. Mengapa ada null di tabel pertama, Anda akan mengetahuinya jika Anda membaca tentang JOIN SQL . Jadi, kita sudah selesai dengan pertanyaan ke database, saya yakin Anda masih memiliki banyak pertanyaan, tapi saya harap Anda akan mencari jawabannya, saya mencoba menyorot jalur pencarian. Mari kita coba merangkum semua yang telah kita pelajari selama ini: 1. Anda dapat menjalankan server web di Spring dan itu tidak sulit. 2. Untuk memahami cara kerjanya, Anda perlu mendalami teori. Tentang buku Artikel tentang musim semi Artikel tentang hal-hal yang berguna 3. Agar pemahaman berubah menjadi kode fisik, Anda perlu membuat kode, dan sebelum melanjutkan, dapatkan proyek sederhana tentang boot musim semi. Dan lebih baik tidak menyalin kode tertulis, tetapi menulis ulang. Saya akan memposting proyek yang sedang Anda dan saya kerjakan di sini, namun saya akan mengandalkan kesadaran Anda dan saya yakin Anda tidak akan sembarangan menyalin-menempel. Tautan ke repositori git clone https://FromJava@bitbucket.org/FromJava/jd.git Bagi mereka yang tidak tahu cara menggunakan tautan ini, saya sarankan untuk menerapkan dua proyek pelatihan: Proyek tentang mengecat mobil: Kelas satu: CarEntity{ Integer pengenal; Nama model string; warna tali; } Kelas kedua: ColorEntity{ Integer id; warna tali; harga bilangan bulat; } Isi database (buat nama yang realistis agar lebih mudah dipahami), implementasikan: , entitas, repositori, layanan, buat kueri standar dan lintas tabel (Berapa biaya untuk mengecat BMW merah? Apa warnanya? yang paling mahal? Tulis model ke konsol dalam urutan abjad dan lain-lain); Proyek perpustakaan: Kelas pertama: BookEntity{ Integer id; Nama stringBuku; Tahun bilangan bulatCreat; Id otomatis bilangan bulat; } Kelas kedua: AutorEntity{ Integer id; String nama depanPengarang; StringnamaakhirPengarang; } Isi database (buat nama yang realistis agar lebih mudah dipahami), implementasi: entitas, repositori, layanan, buat kueri standar dan antar tabel (Siapa yang menulis buku yang mana? Buku mana yang ditulis pertama kali? Buku mana yang ditulis? dari tahun 1800 hingga 1900? Penulis manakah yang paling banyak menulis buku?); Contoh pengisian database proyek "Perpustakaan". Tabel buku BookEntity(id=1, nameBook=Celakalah dari Kecerdasan, 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) Tabel penulis 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 beruntung semuanya, sampai jumpa lagi!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION