JavaRush /Blog Java /Random-VI /Mùa xuân không đáng sợ hay cách đặt câu hỏi về cơ sở dữ l...
Павел
Mức độ

Mùa xuân không đáng sợ hay cách đặt câu hỏi về cơ sở dữ liệu

Xuất bản trong nhóm
NỘI DUNG CỦA CHU KỲ BÀI VIẾT Hôm nay, chúng tôi đang hoàn thiện công việc với cơ sở dữ liệu như một phần của dự án của mình. Nếu bạn đã làm mọi thứ chính xác thì bạn sẽ có một pom với các phần phụ thuộc sau:
<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>
Và đây là cấu trúc của dự án: Mùa xuân không đáng sợ hay cách đặt câu hỏi về cơ sở dữ liệu - 1 Bạn có biết lâu rồi chúng ta chưa nhớ đến ai không? Đây là application.yml, chúng ta chưa nói nhiều về nó ở một trong những bài viết trước. Bây giờ hãy tiếp tục và xóa nó! Vâng, vâng xóa và thế là xong! Nếu chúng ta khởi động dự án ngay bây giờ, mọi thứ sẽ hoạt động như trước, hãy thử cách này. Điều này xảy ra vì bản thân Spring đã được cấu hình với cài đặt mặc định. Bây giờ chúng ta cần đưa tệp yml của mình trở lại thư mục tài nguyên, chúng ta vẫn sẽ cần nó: application.yml (tên phải giống nhau)
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
Lần trước, chúng tôi đã triển khai một số truy vấn tới cơ sở dữ liệu bằng các phương thức của giao diện 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);
}
Nếu bạn đọc về SQL , như tôi đã yêu cầu bạn làm lần trước, thì bạn nên biết rằng những hành động như vậy với cơ sở dữ liệu phải được thực hiện bằng truy vấn SQL. Nhưng không có gợi ý nào về điều này trong dự án, ngay cả trong nhật ký giao diện điều khiển cũng không có gì tương tự. Hãy tìm chúng, mở application.yml, tìm dòng show-sql: ở đó (show sql) và đổi false thành true. Chúng tôi khởi chạy dự án và nhìn vào bảng điều khiển, các nhật ký chứa đầy các mục mới rất giống với SQL, trên thực tế, hầu hết chúng đều không khó hiểu, ví dụ:
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))
Nhưng mục này có thể đặt ra rất nhiều câu hỏi vì những dấu hỏi của nó:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Hãy suy nghĩ một cách logic: Đầu tiên chúng ta thấy từ Hibernate, có nghĩa là anh chàng bí mật này đã đặt bàn chân đầy lông của mình vào đây. Sau khi đọc về anh ấy trên Internet, chúng tôi biết rằng anh ấy Hiber là người triển khai mô hình ORM. Mô hình quan hệ đối tượng mô tả mối quan hệ giữa các đối tượng phần mềm và các bản ghi trong cơ sở dữ liệu. Cố định ý tưởng này rồi, chúng ta tiếp tục suy nghĩ logic: Một mặt, chúng ta có một đối tượng FruitEntity , nó có ba trường: Id số nguyên; Chuỗi tên trái cây; Mã nhà cung cấp số nguyên. Mặt khác, chúng ta có một bảng trong cơ sở dữ liệu Fruit_table với các trường kiểu số nguyên id_fruit , kiểu Fruit_name varchar(255) , kiểu số nguyên nhà cung cấp_code . Nói một cách đại khái, Hibernate lấy một đối tượng FruitEntity , lấy ra các giá trị của các trường của đối tượng và ghi chúng vào các trường bảng tương ứng. Tôi có một câu hỏi dành cho bạn: Hãy nhìn xem, trong lớp InitiateUtils , chúng tôi đã triển khai việc điền vào bảng trái cây, nhưng vì lý do nào đó chúng tôi chỉ đặt giá trị thành hai trường, trường thứ ba ở đâu?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Tôi chắc chắn rằng bạn sẽ tự mình tìm ra điều này, ngoài ra, chúng tôi đã đề cập ngắn gọn về vấn đề này trong bài viết trước đó. Đầu tiên, hãy tìm ra lĩnh vực nào không có ở đây, sau đó bạn sẽ hiểu mọi thứ. Tốt lắm, Hiber đã tạo ra rất nhiều yêu cầu cho chúng tôi. Nhưng chúng ta không mù quáng, hãy triển khai thêm một vài phương thức từ giao diện JpaRepository<> trong lớp 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);
}
Triển khai các phương thức tương tự trong lớp ProviderService. Sau đó, sử dụng chúng trong lớp InitiateUtils cho FruitEntityProviderEntity rồi in kết quả ra bảng điều khiển. (Nhân tiện, nếu bạn chưa biết, bạn có thể nhanh chóng viết “System.out.println()” bằng cách gõ sout và nhấn enter, điều tương tự cũng xảy ra với “public static void main(String[] args){} ” chỉ cần gõ psvm và thế là xong, v.v. ). Tôi nghĩ bạn đã giải quyết xong và chúng ta đã sẵn sàng tiếp tục. Hãy vào giao diện FruitRepository và bắt đầu nhập vào đó (cụ thể là gõ chứ không phải sao chép) phương thức sau: List<FruitEntity> f Bạn sẽ nhận được kết quả sau: Mùa xuân không đáng sợ hay cách đặt câu hỏi về cơ sở dữ liệu - 2 Chỉ cần gọi phương thức đó như thể bạn đang soạn một truy vấn: findById(Integer id ) - tìm một đối tượng theo id; countFruitEntityByFruitName(String name) - sẽ đếm số lượng trái cây có tên cụ thể; Đây là các truy vấn được tạo bởi tên của phương thức; hãy nhớ đọc về chúng và triển khai phương thức between(Integer from, Integer to) trong lớp FruitService để tìm kiếm List<FruitEntity> theo các giá trị của trường Provider_code có trong một khoảng thời gian nhất định và hiển thị kết quả công việc trong bảng điều khiển. Ví dụ: tìm tất cả các loại trái cây có số nhà cung cấp từ 5 đến 7. Đừng vội đọc thêm cho đến khi bạn thực hiện được phương pháp, sẽ không mất nhiều thời gian. Như bạn có thể đã đọc trong bài viết về truy vấn theo tên phương thức: “Bạn không thể viết tất cả các truy vấn như thế này, nhưng có thể viết những truy vấn đơn giản”. Đối với các truy vấn phức tạp hơn, chú thích @Query được sử dụng và JPQL được sử dụng thay vì SQL (cũng lưu ý đến bài viết này). Đối với dự án của chúng tôi, bạn có thể thực hiện các truy vấn JOIN, như sau:
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();

}
Một truy vấn SQL tiêu chuẩn sẽ là: "select Fruit_table.fruit_name, Provider_table.provider_name from Fruit_table left join Provider_table on Fruit_table.provider_code = Provider_table.id". Tại đây, bạn có thể dễ dàng thiết lập sự tương ứng: f ruit_tableFruitEntiy f, trong đó FruitEntiy là loại biến, f là tên của nó, nghĩa là SQL hoạt động với các bảng và trường và JPQL với các đối tượng và trường của chúng. Một lần nữa Fruit_table.fruit_namef.fruitName ; Vì chúng ta làm việc với các đối tượng nên chúng ta có thể xuất ra đối tượng: Hãy viết một phương thức FruitRepository khác
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Hãy triển khai cả hai phương thức trong lớp FruitService
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
Nghe có vẻ không tệ nhưng họ vẫn sử dụng SQL cũ tốt cho các truy vấn phức tạp
@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();
Và chúng tôi sử dụng tất cả chúng trong lớp 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);
        }
Chúng tôi khởi chạy dự án và thấy các nhật ký mới trong bảng điều khiển: Bảng trái cây và các nhà cung cấp của chúng Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Bảng các loại trái cây và chúng nhà cung cấp FruitEntity(id= 2, FruitName=Fruit2, ProviderCode=5) FruitEntity(id=3, FruitName=Fruit3, ProviderCode=2) FruitEntity(id=4, FruitName=Fruit4, ProviderCode=5) Bảng các loại trái cây và nhà cung cấp Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Có, nếu bạn đã chán "giả" và chỉ truy vấn SQL trong bảng điều khiển, bạn có thể trả về false ở vị trí của nó trong tệp yaml. Tại sao lại có giá trị rỗng trong bảng đầu tiên, bạn sẽ biết nếu đọc về JOIN SQL . Và như vậy, chúng ta đã hoàn thành các truy vấn tới cơ sở dữ liệu, tôi chắc chắn rằng bạn vẫn còn nhiều câu hỏi, nhưng tôi hy vọng rằng bạn sẽ tìm kiếm câu trả lời cho chúng, tôi đã cố gắng đánh dấu các đường dẫn tìm kiếm. Hãy thử tóm tắt lại mọi thứ chúng ta đã học được trong thời gian này: 1. Bạn có thể chạy một máy chủ web trong Spring và điều đó không khó. 2. Để hiểu cách thức hoạt động của nó, bạn cần đi sâu vào lý thuyết. Giới thiệu sách Bài viết về mùa xuân Bài viết về những điều hữu ích 3. Để hiểu để biến thành mã vật lý, bạn cần phải viết mã và trước khi tiếp tục, hãy bắt tay vào các dự án đơn giản trên spring-boot. Và tốt hơn hết là đừng sao chép mã đã viết mà hãy viết lại nó. Tôi sẽ đăng dự án mà tôi và bạn đang thực hiện ở đây, nhưng tôi sẽ dựa vào nhận thức của bạn và tôi chắc chắn rằng bạn sẽ không sao chép-dán một cách thiếu suy nghĩ. Liên kết tới kho lưu trữ git clone https://FromJava@bitbucket.org/FromJava/jd.git Đối với những người chưa biết cách sử dụng liên kết này, tôi khuyên bạn nên thực hiện hai dự án đào tạo: Dự án về sơn ô tô: Lớp đầu tiên: CarEntity{ Integer nhận dạng; Tên mẫu chuỗi; Màu dây; } Lớp thứ hai: ColorEntity{ Id số nguyên; Màu dây; Giá nguyên; } Điền vào cơ sở dữ liệu (đặt tên thực tế để dễ hiểu hơn), triển khai: , thực thể, kho lưu trữ, dịch vụ, tạo truy vấn tiêu chuẩn và bảng chéo (Sơn màu đỏ BMW bao nhiêu? Màu gì là màu gì? đắt nhất Viết mô hình vào bảng điều khiển theo thứ tự bảng chữ cái, v.v.); Dự án thư viện: Lớp đầu tiên: BookEntity{ Id số nguyên; Tên chuỗiBook; Năm nguyênTạo; autorId số nguyên; } Lớp thứ hai: AutorEntity{ Id số nguyên; Chuỗi firstNameAutor; Chuỗi LastNameAutor; } Điền vào cơ sở dữ liệu (đặt tên thực tế để dễ hiểu hơn), triển khai: thực thể, kho lưu trữ, dịch vụ, tạo truy vấn chuẩn và liên bảng (Ai đã viết cuốn sách nào? Cuốn sách nào được viết trước? Sách nào được viết từ năm 1800 đến năm 1900? Tác giả nào viết nhiều sách nhất?); Ví dụ về điền vào cơ sở dữ liệu dự án "Thư viện" Bảng sách 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) Bảng tác giả 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) Chúc mọi người may mắn, hẹn gặp lại!
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION