Bài tập vê jdbc hay có hướng dẫn năm 2024

Hôm nay chúng ta sẽ thực hiện dự án cuối cùng về mô-đun JRU thứ tư. Nó sẽ là gì? Hãy thử làm việc với các công nghệ khác nhau: MySQL, Hibernate, Redis, Docker. Bây giờ thêm chủ đề.

Nhiệm vụ: chúng tôi có một cơ sở dữ liệu MySQL quan hệ với một lược đồ (quốc gia-thành phố, ngôn ngữ theo quốc gia). Và có một yêu cầu thường xuyên của thành phố, làm chậm lại. Chúng tôi đã đưa ra một giải pháp - chuyển tất cả dữ liệu được yêu cầu thường xuyên sang Redis (trong bộ nhớ lưu trữ kiểu khóa-giá trị).

Và chúng ta không cần tất cả dữ liệu được lưu trữ trong MySQL mà chỉ cần một tập hợp các trường đã chọn. Dự án sẽ ở dạng hướng dẫn. Tức là ở đây chúng ta sẽ nêu vấn đề và giải quyết ngay.

Vì vậy, hãy bắt đầu với phần mềm chúng ta sẽ cần:

  1. IDEA Ultimate (hết key - viết thư cho Roman in the Slack)
  2. Bàn làm việc (hoặc bất kỳ máy khách nào khác cho MySQL)
  3. docker
  4. redis-insight - tùy chọn

Kế hoạch hành động của chúng tôi:

  1. Thiết lập docker (Tôi sẽ không làm điều này trong hướng dẫn, vì mỗi HĐH sẽ có những đặc điểm riêng và có rất nhiều câu trả lời trên Internet cho những câu hỏi như “cách cài đặt docker trên windows”), kiểm tra xem mọi thứ có hoạt động không.
  2. Chạy máy chủ MySQL dưới dạng bộ chứa docker.
  3. Mở rộng kết xuất .
  4. Tạo một dự án trong Idea, thêm các phụ thuộc maven.
  5. Tạo miền lớp.
  6. Viết một phương thức để lấy tất cả dữ liệu từ MySQL.
  7. Viết phương thức chuyển đổi dữ liệu (trong Redis, chúng tôi sẽ chỉ ghi dữ liệu được yêu cầu thường xuyên).
  8. Chạy máy chủ Redis dưới dạng bộ chứa docker.
  9. Ghi dữ liệu vào Redis.
  10. Tùy chọn: cài đặt redis-insight, xem dữ liệu được lưu trữ trong Redis.
  11. Viết phương thức lấy dữ liệu từ Redis.
  12. Viết phương thức lấy dữ liệu từ MySQL.
  13. So sánh tốc độ lấy cùng một dữ liệu từ MySQL và Redis.

thiết lập docker

Docker là một nền tảng mở để phát triển, phân phối và vận hành các ứng dụng. Chúng tôi sẽ sử dụng nó để không cài đặt và định cấu hình Redis trên máy cục bộ mà sử dụng hình ảnh tạo sẵn. Bạn có thể đọc thêm về docker tại đây hoặc xem tại đây . Nếu bạn không quen thuộc với docker, tôi khuyên bạn chỉ nên xem liên kết thứ hai.

Để chắc chắn rằng bạn đã cài đặt và cấu hình docker, hãy chạy lệnh:

package com.codegym.domain;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.util.Set;
@Entity
@Table(schema = "world", name = "country")
public class Country {
    @Id
    @Column(name = "id")
    private Integer id;
    private String code;
    @Column(name = "code_2")
    private String alternativeCode;
    private String name;
    @Column(name = "continent")
    @Enumerated(EnumType.ORDINAL)
    private Continent continent;
    private String region;
    @Column(name = "surface_area")
    private BigDecimal surfaceArea;
    @Column(name = "indep_year")
    private Short independenceYear;
    private Integer population;
    @Column(name = "life_expectancy")
    private BigDecimal lifeExpectancy;
    @Column(name = "gnp")
    private BigDecimal GNP;
    @Column(name = "gnpo_id")
    private BigDecimal GNPOId;
    @Column(name = "local_name")
    private String localName;
    @Column(name = "government_form")
    private String governmentForm;
    @Column(name = "head_of_state")
    private String headOfState;
    @OneToOne
    @JoinColumn(name = "capital")
    private City city;
    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "country_id")
    private Set<CountryLanguage> languages;
    //Getters and Setters omitted
}

2

Nếu mọi thứ đều ổn, bạn sẽ thấy phiên bản docker

Bài tập vê jdbc hay có hướng dẫn năm 2024

Chạy máy chủ MySQL dưới dạng bộ chứa docker

Để có thể so sánh thời gian trả về dữ liệu từ MySQL và Redis, chúng ta cũng sẽ sử dụng MySQL trong docker. Trong PowerShell (hoặc một thiết bị đầu cuối bảng điều khiển khác nếu bạn không sử dụng Windows), hãy chạy lệnh:

docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root --restart unless-stopped -v mysql:/var/lib/mysql mysql:8 

Xem xét những gì chúng tôi đang làm với lệnh này:

  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    3– khởi chạy (và tải xuống, nếu nó chưa được tải xuống máy cục bộ) hình ảnh. Kết quả của việc khởi chạy, chúng tôi nhận được một vùng chứa đang chạy.
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    4- đặt tên của vùng chứa mysql.
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    5- một cờ cho biết rằng bộ chứa sẽ tiếp tục hoạt động, ngay cả khi bạn đóng cửa sổ đầu cuối mà từ đó bộ chứa này được khởi chạy.
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    6- chỉ định cổng. Trước dấu hai chấm - cổng trên máy cục bộ, sau dấu hai chấm - cổng trong vùng chứa.
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    7– chuyển biến môi trường MYSQL_ROOT_PASSWORD với giá trị gốc vào vùng chứa. Gắn cờ cụ thể cho hình ảnh mysql/
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    8- đặt chính sách hành vi (có nên khởi động lại vùng chứa khi đóng hay không). Giá trị unless-stopped có nghĩa là luôn khởi động lại, trừ khi vùng chứa bị dừng /
  • package com.codegym.domain; import jakarta.persistence.*; import java.math.BigDecimal; import java.util.Set; @Entity @Table(schema = "world", name = "country") public class Country {

    @Id  
    @Column(name = "id")  
    private Integer id;  
    private String code;  
    @Column(name = "code_2")  
    private String alternativeCode;  
    private String name;  
    @Column(name = "continent")  
    @Enumerated(EnumType.ORDINAL)  
    private Continent continent;  
    private String region;  
    @Column(name = "surface_area")  
    private BigDecimal surfaceArea;  
    @Column(name = "indep_year")  
    private Short independenceYear;  
    private Integer population;  
    @Column(name = "life_expectancy")  
    private BigDecimal lifeExpectancy;  
    @Column(name = "gnp")  
    private BigDecimal GNP;  
    @Column(name = "gnpo_id")  
    private BigDecimal GNPOId;  
    @Column(name = "local_name")  
    private String localName;  
    @Column(name = "government_form")  
    private String governmentForm;  
    @Column(name = "head_of_state")  
    private String headOfState;  
    @OneToOne  
    @JoinColumn(name = "capital")  
    private City city;  
    @OneToMany(fetch = FetchType.EAGER)  
    @JoinColumn(name = "country_id")  
    private Set<CountryLanguage> languages;  
    //Getters and Setters omitted  
    
    }

    9– thêm khối lượng (hình ảnh để lưu trữ thông tin).
  • package com.codegym.domain; public enum Continent {

    ASIA,  
    EUROPE,  
    NORTH_AMERICA,  
    AFRICA,  
    OCEANIA,  
    ANTARCTICA,  
    SOUTH_AMERICA  
    
    }

    0 – tên của hình ảnh và phiên bản của nó.

Sau khi thực hiện lệnh trong thiết bị đầu cuối, docker sẽ tải xuống tất cả các lớp của hình ảnh và khởi động vùng chứa:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Lưu ý quan trọng: nếu bạn đã cài đặt MySQL như một dịch vụ trên máy tính cục bộ của mình và nó đang chạy, bạn cần chỉ định một cổng khác trong lệnh bắt đầu hoặc dừng dịch vụ đang chạy này.

Bài tập vê jdbc hay có hướng dẫn năm 2024

Mở rộng kết xuất

Để mở rộng kết xuất, bạn cần tạo một kết nối mới tới cơ sở dữ liệu từ Workbench, nơi bạn chỉ định các tham số. Tôi đã sử dụng cổng mặc định (3306), không thay đổi tên người dùng (root theo mặc định) và đặt mật khẩu cho người dùng root (root).

Bài tập vê jdbc hay có hướng dẫn năm 2024

Trong Workbench, thực hiện

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

1và chọn

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

2. Chỉ định nơi bạn đã tải xuống kết xuất dưới dạng tệp . Bạn không cần tạo lược đồ trước - việc tạo lược đồ được bao gồm trong tệp kết xuất. Sau khi nhập thành công, bạn sẽ có một lược đồ thế giới với ba bảng:

  1. city ​​là bảng các thành phố.
  2. quốc gia - bảng quốc gia.
  3. country_language - một bảng cho biết tỷ lệ phần trăm dân số trong quốc gia nói một ngôn ngữ cụ thể.

Bài tập vê jdbc hay có hướng dẫn năm 2024

Vì chúng tôi đã sử dụng một ổ đĩa khi khởi động bộ chứa, nên sau khi dừng và thậm chí xóa bộ chứa mysql và thực hiện lại lệnh bắt đầu (

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

3), sẽ không cần phải triển khai kết xuất lại - nó đã được triển khai trong ổ đĩa.

Tạo dự án trong Idea, thêm phụ thuộc maven

Bạn đã biết cách tạo một dự án trong Ý tưởng - đây là điểm dễ nhất trong dự án ngày nay.

Bài tập vê jdbc hay có hướng dẫn năm 2024

Thêm phụ thuộc vào tệp pom:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

Ba phụ thuộc đầu tiên từ lâu đã quen thuộc với bạn.

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

4là một trong những ứng dụng khách Java có sẵn để làm việc với Redis.

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

5– phụ thuộc vào việc sử dụng ObjectMapper (để chuyển đổi dữ liệu để lưu trữ trong Redis (khóa-giá trị của kiểu Chuỗi)).

Cũng trong thư mục tài nguyên (src/main/resource) thêm spy.properties để xem các yêu cầu với các tham số mà Hibernate thực thi. Nội dung tệp:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

Tạo miền lớp

Tạo gói com.codegym.domain

Tôi thấy thuận tiện khi ánh xạ các bảng trên một thực thể để sử dụng cấu trúc bảng trong Ý tưởng, vì vậy hãy thêm kết nối cơ sở dữ liệu vào Ý tưởng.

Bài tập vê jdbc hay có hướng dẫn năm 2024
Bài tập vê jdbc hay có hướng dẫn năm 2024

Tôi đề xuất tạo các thực thể theo thứ tự sau:

  • Quốc gia
  • thành phố
  • Đất NướcNgôn Ngữ

Bạn nên tự mình thực hiện việc lập bản đồ.

Mã lớp quốc gia:

package com.codegym.domain;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.util.Set;
@Entity
@Table(schema = "world", name = "country")
public class Country {
    @Id
    @Column(name = "id")
    private Integer id;
    private String code;
    @Column(name = "code_2")
    private String alternativeCode;
    private String name;
    @Column(name = "continent")
    @Enumerated(EnumType.ORDINAL)
    private Continent continent;
    private String region;
    @Column(name = "surface_area")
    private BigDecimal surfaceArea;
    @Column(name = "indep_year")
    private Short independenceYear;
    private Integer population;
    @Column(name = "life_expectancy")
    private BigDecimal lifeExpectancy;
    @Column(name = "gnp")
    private BigDecimal GNP;
    @Column(name = "gnpo_id")
    private BigDecimal GNPOId;
    @Column(name = "local_name")
    private String localName;
    @Column(name = "government_form")
    private String governmentForm;
    @Column(name = "head_of_state")
    private String headOfState;
    @OneToOne
    @JoinColumn(name = "capital")
    private City city;
    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "country_id")
    private Set<CountryLanguage> languages;
    //Getters and Setters omitted
}

Có 3 điểm thú vị trong mã.

Đầu tiên là Continent enam , được lưu trữ trong cơ sở dữ liệu dưới dạng giá trị thứ tự. Trong cấu trúc của bảng quốc gia, trong phần nhận xét cho trường lục địa, bạn có thể xem giá trị số nào tương ứng với lục địa nào.

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

Điểm thứ hai là một tập hợp các thực thể

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

6 . Đây là một liên kết

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

7không có trong bản nháp thứ hai của mô-đun này. Theo mặc định, Hibernate sẽ không lấy giá trị của tập hợp này khi yêu cầu một thực thể quốc gia. Nhưng vì chúng ta cần trừ tất cả các giá trị khỏi cơ sở dữ liệu quan hệ để lưu vào bộ nhớ đệm, tệp

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

8.

Thứ ba là lĩnh vực thành phố . Giao tiếp

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

9- giống như mọi thứ đều quen thuộc và dễ hiểu. Nhưng, nếu chúng ta nhìn vào cấu trúc khóa ngoại trong cơ sở dữ liệu, chúng ta thấy rằng quốc gia (quốc gia) có liên kết đến thủ đô (thành phố) và thành phố (thành phố) có liên kết đến quốc gia (quốc gia). Có một mối quan hệ theo chu kỳ.

Chúng tôi sẽ chưa làm bất cứ điều gì với mục này, nhưng khi chúng tôi đến mục “Viết phương pháp để lấy tất cả dữ liệu từ MySQL”, hãy xem những truy vấn mà Hibernate thực thi, xem số của chúng và ghi nhớ mục này.

Mã lớp thành phố:

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

Mã lớp CountryLanguage:

package com.codegym.domain;
import jakarta.persistence.*;
import org.hibernate.annotations.Type;
import java.math.BigDecimal;
@Entity
@Table(schema = "world", name = "country_language")
public class CountryLanguage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String language;
    @Column(name = "is_official", columnDefinition = "BIT")
    @Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isOfficial;
    private BigDecimal percentage;
    //Getters and Setters omitted
}

Viết một phương thức để lấy tất cả dữ liệu từ MySQL

Trong lớp Main, chúng ta khai báo các trường:

private final SessionFactory sessionFactory;
private final RedisClient redisClient;
private final ObjectMapper mapper;
private final CityDAO cityDAO;
private final CountryDAO countryDAO;

và khởi tạo chúng trong hàm tạo của lớp Chính:

public Main() {
    sessionFactory = prepareRelationalDb();
    cityDAO = new CityDAO(sessionFactory);
    countryDAO = new CountryDAO(sessionFactory);
    redisClient = prepareRedisClient();
    mapper = new ObjectMapper();
}

Như bạn có thể thấy, không có đủ phương thức và lớp - hãy viết chúng.

Khai báo một gói com.codegym.dao và thêm 2 lớp vào đó:

package com.codegym.dao;
import com.codegym.domain.Country;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import java.util.List;
public class CountryDAO {
    private final SessionFactory sessionFactory;
    public CountryDAO(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    public List<Country> getAll() {
        Query<Country> query = sessionFactory.getCurrentSession().createQuery("select c from Country c", Country.class);
        return query.list();
    }
}

<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

0

Bây giờ bạn có thể nhập 2 lớp này vào Main. Vẫn còn thiếu hai phương pháp:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

1

Chúng tôi vẫn chưa tiếp cận củ cải, vì vậy việc triển khai khởi tạo ứng dụng khách củ cải sẽ vẫn còn sơ khai:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

2

Cuối cùng, chúng ta có thể viết một phương thức để lấy ra tất cả các thành phố:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

3

Tính năng triển khai sao cho mỗi thành phố chúng tôi nhận được 500 thành phố. Điều này là cần thiết vì có những hạn chế về lượng dữ liệu được truyền. Vâng, trong trường hợp của chúng tôi, chúng tôi sẽ không đến với họ, bởi vì. chúng tôi có tổng cộng 4079 thành phố trong cơ sở dữ liệu. Nhưng trong các ứng dụng sản xuất, khi bạn cần lấy nhiều dữ liệu, kỹ thuật này thường được sử dụng.

Và việc thực hiện các phương pháp chính:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

4

Bây giờ chúng ta có thể chạy ứng dụng của mình ở chế độ gỡ lỗi lần đầu tiên và xem nó hoạt động như thế nào (hoặc không hoạt động - vâng, điều này thường xảy ra).

Bài tập vê jdbc hay có hướng dẫn năm 2024

Các thành phố đang nhận được. Mỗi thành phố có một quốc gia, nếu nó chưa được trừ khỏi cơ sở dữ liệu cho một thành phố khác. Hãy tính toán sơ bộ có bao nhiêu truy vấn mà Hibernate sẽ gửi đến cơ sở dữ liệu:

  • 1 yêu cầu tìm tổng số thành phố (cần lặp lại hơn 500 thành phố để biết khi nào nên dừng).
  • 4079/500 = 9 yêu cầu (danh sách các thành phố).
  • Mỗi thành phố được một quốc gia, nếu nó chưa được trừ trước đó. Vì có 239 quốc gia trong cơ sở dữ liệu, điều này sẽ cung cấp cho chúng tôi 239 truy vấn.

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

0. Và chúng tôi cũng nói rằng cùng với đất nước, chúng tôi sẽ ngay lập tức nhận được một bộ ngôn ngữ, nếu không sẽ có bóng tối nói chung. Nhưng nó vẫn còn rất nhiều, vì vậy hãy điều chỉnh hành vi một chút. Hãy bắt đầu với những suy nghĩ: phải làm gì, chạy đi đâu? Nhưng nghiêm túc - tại sao lại có nhiều yêu cầu như vậy. Nếu bạn xem nhật ký yêu cầu, chúng tôi thấy rằng mỗi quốc gia được yêu cầu riêng biệt, vì vậy, giải pháp đơn giản đầu tiên: hãy cùng nhau yêu cầu tất cả các quốc gia, vì chúng tôi biết trước rằng chúng tôi sẽ cần tất cả các quốc gia đó trong giao dịch này.

Trong phương thức fetchData(), ngay sau khi bắt đầu giao dịch, hãy thêm dòng sau:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

5

Chúng tôi tính các yêu cầu:

  • 1 - nhận tất cả các quốc gia
  • 239 - truy vấn cho từng quốc gia có thủ đô
  • 1 - yêu cầu số lượng thành phố
  • 9 - yêu cầu danh sách các thành phố

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

1. Ý tưởng là tốt, nhưng nó đã không làm việc. Vấn đề là đất nước có mối liên hệ với thủ đô (thành phố)

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

9. Và một liên kết như vậy được tải ngay lập tức theo mặc định (

package com.codegym.domain;
public enum Continent {
    ASIA,
    EUROPE,
    NORTH_AMERICA,
    AFRICA,
    OCEANIA,
    ANTARCTICA,
    SOUTH_AMERICA
}

8). Hãy đặt

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

4, bởi vì dù sao đi nữa, chúng tôi sẽ tải tất cả các thành phố sau trong cùng một giao dịch.


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

6

Viết hoa không còn được yêu cầu riêng, nhưng số lượng yêu cầu không thay đổi. Bây giờ, đối với mỗi quốc gia, danh sách Ngôn ngữ Quốc gia được yêu cầu bởi một truy vấn riêng biệt . Đó là, có sự tiến bộ, và chúng ta đang đi đúng hướng. Nếu bạn còn nhớ, các bài giảng đã đề xuất giải pháp “tìm nạp tham gia” để yêu cầu một thực thể có dữ liệu phụ thuộc trong một yêu cầu bằng cách thêm một tham gia bổ sung vào yêu cầu. Trong CountryDAO , viết lại truy vấn HQL trong phương thức

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

5thành:


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

7

Phóng. Chúng tôi xem nhật ký, đếm yêu cầu:

  • 1 - tất cả các quốc gia có ngôn ngữ
  • 1 - số thành phố
  • 9 - danh sách các thành phố.

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

6- chúng tôi đã thành công)) Nếu bạn không chỉ đọc tất cả văn bản này mà còn cố chạy nó sau mỗi bước điều chỉnh ứng dụng, bạn thậm chí nên lưu ý trực quan nhiều lần khả năng tăng tốc của toàn bộ ứng dụng.

Viết phương thức chuyển đổi dữ liệu

Hãy tạo một gói

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

7trong đó chúng ta thêm 2 lớp: CityCountry (dữ liệu về thành phố và quốc gia nơi thành phố này tọa lạc) và Language (dữ liệu về ngôn ngữ). Dưới đây là tất cả các trường thường được yêu cầu “theo nhiệm vụ” trong “yêu cầu phanh”.


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

8


<dependencies> 
   <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>8.0.30</version> 
   </dependency> 
   <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-core-jakarta</artifactId> 
      <version>5.6.14.Final</version> 
   </dependency> 
   <dependency> 
      <groupId>p6spy</groupId> 
      <artifactId>p6spy</artifactId> 
      <version>3.9.1</version> 
   </dependency> 
   <dependency> 
      <groupId>io.lettuce</groupId> 
      <artifactId>lettuce-core</artifactId> 
      <version>6.2.2.RELEASE</version> 
   </dependency> 
   <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.14.0</version> 
   </dependency> 
</dependencies> 

9

Trong phương thức chính, sau khi nhận được tất cả các thành phố, hãy thêm dòng

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

0

Và thực hiện phương pháp này:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

1

Tôi nghĩ phương pháp này dễ hiểu: chúng ta chỉ cần tạo một thực thể CityCountry và điền dữ liệu từ City , Country , CountryLanguage vào đó .

Chạy máy chủ Redis dưới dạng bộ chứa docker

Có 2 lựa chọn ở đây. Nếu bạn thực hiện bước tùy chọn "cài đặt redis-insight, xem dữ liệu được lưu trữ trong Redis", thì lệnh này dành cho bạn:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

2

Nếu bạn quyết định bỏ qua bước này, thì chỉ cần:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

3

Sự khác biệt là trong tùy chọn đầu tiên, cổng 8001 được chuyển tiếp đến máy cục bộ mà bạn có thể kết nối với máy khách bên ngoài để xem những gì được lưu trữ bên trong. Và tôi đã từng đặt những cái tên có ý nghĩa, do đó,

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

8hoặc

package com.codegym.domain;
import jakarta.persistence.*;
@Entity
@Table(schema = "world", name = "city")
public class City {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String district;
    private Integer population;
    //Getters and Setters omitted
}

9.

Sau khi khởi chạy, bạn có thể xem danh sách các vùng chứa đang chạy. Để làm điều này, hãy chạy lệnh:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

4

Và bạn sẽ thấy một cái gì đó như thế này:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Nếu bạn cần tìm lệnh nào đó, bạn có thể xem phần trợ giúp trong terminal (trợ giúp docker) hoặc google "how to..." (ví dụ: docker cách loại bỏ container đang chạy).

Và chúng tôi cũng đã gọi việc khởi tạo ứng dụng khách củ cải trong hàm tạo Chính, nhưng không thực hiện chính phương thức đó. Thêm triển khai:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

5

sout đã được thêm vào cho mục đích giáo dục để trong nhật ký khởi chạy, bạn có thể thấy rằng mọi thứ đều ổn và kết nối thông qua ứng dụng củ cải được thông qua mà không có lỗi.

Ghi dữ liệu vào Redis

Thêm một cuộc gọi đến phương pháp chính

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

6

Với việc thực hiện phương pháp này:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

7

Tại đây, một kết nối đồng bộ được mở với máy khách củ cải và tuần tự từng đối tượng thuộc loại CityCountry được ghi vào củ cải. Vì củ cải là một kho lưu trữ khóa-giá trị Chuỗi nên khóa (id thành phố) được chuyển đổi thành một chuỗi. Và giá trị cũng là chuỗi, nhưng sử dụng ObjectMapper ở định dạng JSON.

Nó vẫn còn để chạy và kiểm tra xem không có lỗi trong nhật ký. Mọi thứ đã hoạt động.

Cài đặt redis-insight, xem dữ liệu được lưu trữ trong Redis (tùy chọn)

Tải xuống redis-insight từ liên kết và cài đặt nó. Sau khi bắt đầu, nó ngay lập tức hiển thị đối tượng củ cải của chúng ta trong vùng chứa docker:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Nếu bạn đăng nhập, chúng ta sẽ thấy danh sách tất cả các khóa:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Và bạn có thể vào bất kỳ phím nào để xem dữ liệu nào được lưu trữ trên đó:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Viết phương thức lấy dữ liệu từ Redis

Để thử nghiệm, chúng tôi sử dụng thử nghiệm sau: chúng tôi nhận được 10 bản ghi CityCountry. Mỗi người có một yêu cầu riêng biệt, nhưng trong một kết nối.

Dữ liệu từ củ cải có thể được lấy thông qua khách hàng củ cải của chúng tôi. Để làm điều này, hãy viết một phương thức nhận danh sách id.

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

8

Tôi nghĩ rằng việc triển khai là trực quan: chúng tôi mở một kết nối đồng bộ và với mỗi id , chúng tôi nhận được một Chuỗi JSON , mà chúng tôi chuyển đổi thành đối tượng của loại CityCountry mà chúng tôi cần .

Viết phương thức lấy dữ liệu từ MySQL

Trong lớp CityDAO , hãy thêm một phương thức

package com.codegym.domain;
import jakarta.persistence.*;
import org.hibernate.annotations.Type;
import java.math.BigDecimal;
@Entity
@Table(schema = "world", name = "country_language")
public class CountryLanguage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String language;
    @Column(name = "is_official", columnDefinition = "BIT")
    @Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isOfficial;
    private BigDecimal percentage;
    //Getters and Setters omitted
}

0trong đó chúng ta sẽ lấy thành phố cùng với quốc gia:

driverlist=com.mysql.cj.jdbc.Driver 
dateformat=yyyy-MM-dd hh:mm:ss a 
appender=com.p6spy.engine.spy.appender.StdoutLogger 
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat 

9

Tương tự như đoạn trước, hãy thêm một phương thức tương tự cho MySQL vào lớp Chính:

package com.codegym.domain;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.util.Set;
@Entity
@Table(schema = "world", name = "country")
public class Country {
    @Id
    @Column(name = "id")
    private Integer id;
    private String code;
    @Column(name = "code_2")
    private String alternativeCode;
    private String name;
    @Column(name = "continent")
    @Enumerated(EnumType.ORDINAL)
    private Continent continent;
    private String region;
    @Column(name = "surface_area")
    private BigDecimal surfaceArea;
    @Column(name = "indep_year")
    private Short independenceYear;
    private Integer population;
    @Column(name = "life_expectancy")
    private BigDecimal lifeExpectancy;
    @Column(name = "gnp")
    private BigDecimal GNP;
    @Column(name = "gnpo_id")
    private BigDecimal GNPOId;
    @Column(name = "local_name")
    private String localName;
    @Column(name = "government_form")
    private String governmentForm;
    @Column(name = "head_of_state")
    private String headOfState;
    @OneToOne
    @JoinColumn(name = "capital")
    private City city;
    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "country_id")
    private Set<CountryLanguage> languages;
    //Getters and Setters omitted
}

0

Trong số các tính năng, để chắc chắn nhận được đầy đủ đối tượng (không có sơ khai proxy), chúng tôi yêu cầu rõ ràng danh sách các ngôn ngữ từ quốc gia.

So sánh tốc độ lấy cùng một dữ liệu từ MySQL và Redis

Ở đây tôi sẽ cung cấp ngay mã của phương thức chính và kết quả thu được trên máy tính cục bộ của tôi.

package com.codegym.domain;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.util.Set;
@Entity
@Table(schema = "world", name = "country")
public class Country {
    @Id
    @Column(name = "id")
    private Integer id;
    private String code;
    @Column(name = "code_2")
    private String alternativeCode;
    private String name;
    @Column(name = "continent")
    @Enumerated(EnumType.ORDINAL)
    private Continent continent;
    private String region;
    @Column(name = "surface_area")
    private BigDecimal surfaceArea;
    @Column(name = "indep_year")
    private Short independenceYear;
    private Integer population;
    @Column(name = "life_expectancy")
    private BigDecimal lifeExpectancy;
    @Column(name = "gnp")
    private BigDecimal GNP;
    @Column(name = "gnpo_id")
    private BigDecimal GNPOId;
    @Column(name = "local_name")
    private String localName;
    @Column(name = "government_form")
    private String governmentForm;
    @Column(name = "head_of_state")
    private String headOfState;
    @OneToOne
    @JoinColumn(name = "capital")
    private City city;
    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "country_id")
    private Set<CountryLanguage> languages;
    //Getters and Setters omitted
}

1

Khi thử nghiệm, có một tính năng - dữ liệu từ MySQL chỉ được đọc nên không thể khởi động lại giữa các lần khởi chạy ứng dụng của chúng tôi. Và trong Redis chúng được viết.

Mặc dù khi bạn cố gắng thêm một bản sao cho cùng một khóa, dữ liệu sẽ chỉ được cập nhật, tôi khuyên bạn nên chạy các lệnh để dừng vùng chứa

package com.codegym.domain;
import jakarta.persistence.*;
import org.hibernate.annotations.Type;
import java.math.BigDecimal;
@Entity
@Table(schema = "world", name = "country_language")
public class CountryLanguage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String language;
    @Column(name = "is_official", columnDefinition = "BIT")
    @Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isOfficial;
    private BigDecimal percentage;
    //Getters and Setters omitted
}

1và xóa vùng chứa giữa các lần khởi chạy ứng dụng trong thiết bị đầu cuối

package com.codegym.domain;
import jakarta.persistence.*;
import org.hibernate.annotations.Type;
import java.math.BigDecimal;
@Entity
@Table(schema = "world", name = "country_language")
public class CountryLanguage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String language;
    @Column(name = "is_official", columnDefinition = "BIT")
    @Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isOfficial;
    private BigDecimal percentage;
    //Getters and Setters omitted
}

2. Sau đó, nâng thùng chứa củ cải lên một lần nữa

package com.codegym.domain;
import jakarta.persistence.*;
import org.hibernate.annotations.Type;
import java.math.BigDecimal;
@Entity
@Table(schema = "world", name = "country_language")
public class CountryLanguage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;
    private String language;
    @Column(name = "is_official", columnDefinition = "BIT")
    @Type(type = "org.hibernate.type.NumericBooleanType")
    private Boolean isOfficial;
    private BigDecimal percentage;
    //Getters and Setters omitted
}

3và chỉ sau đó thực hiện ứng dụng của chúng tôi.

Đây là kết quả kiểm tra của tôi:

Bài tập vê jdbc hay có hướng dẫn năm 2024

Tổng cộng, chúng tôi đã đạt được mức tăng hiệu suất phản hồi đối với yêu cầu "đạp phanh thường xuyên" lên một lần rưỡi. Và điều này có tính đến thực tế là trong quá trình thử nghiệm, chúng tôi đã sử dụng không phải phương pháp khử lưu huỳnh nhanh nhất thông qua ObjectMapper . Nếu bạn thay đổi nó thành GSON, rất có thể, bạn có thể "giành" thêm một chút thời gian.

Tại thời điểm này, tôi nhớ một câu chuyện cười về một lập trình viên và thời gian: hãy đọc và suy nghĩ về cách viết và tối ưu hóa mã của bạn.