JavaRush /مدونة جافا /Random-AR /الربيع ليس مخيفًا، أو كيفية طرح سؤال في قاعدة البيانات
Павел
مستوى

الربيع ليس مخيفًا، أو كيفية طرح سؤال في قاعدة البيانات

نشرت في المجموعة
محتويات دورة المقالات اليوم نقوم بوضع اللمسات الأخيرة على العمل مع قاعدة البيانات كجزء من مشروعنا. إذا فعلت كل شيء بشكل صحيح، فمن المفترض أن يكون لديك pom بالتبعيات التالية:
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <java.version>1.8</java.version>
</properties>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath/><!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
وهنا هيكل المشروع: الربيع ليس مخيفًا، أو كيفية طرح سؤال في قاعدة البيانات - 1 هل تعرف من لم نتذكره لفترة طويلة؟ هذا هو application.yml، لم نتحدث عنه كثيرًا في أحد المقالات السابقة. الآن دعونا نمضي قدمًا ونحذفه! نعم، نعم حذف وهذا كل شيء! إذا أطلقنا المشروع الآن، كل شيء سيعمل كما كان من قبل، جرب هذا. حدث هذا لأنه تم تكوين Spring نفسه بالإعدادات الافتراضية. نحتاج الآن إلى إعادة ملف yml الخاص بنا إلى مجلد الموارد، وسنظل بحاجة إليه: application.yml (يجب أن يكون الاسم هو نفسه)
spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:test;
    username: sa
    password:
    h2:
      console:
        enabled: true
  jpa:
    hibernate.ddl-auto: create
    generate-ddl: true
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
في المرة الأخيرة، قمنا بتنفيذ عدة استعلامات لقاعدة البيانات باستخدام طرق واجهة JpaRepository<>:
//сохранить одну запись в таблицу фруктов
public void save(FruitEntity fruitEntity){
    fruitRepository.save(fruitEntity);
}
//получить все записи из таблицы фруктов
public List<FruitEntity> getAll(){
   return fruitRepository.findAll();
}
//сохранить несколько записей в таблицу фруктов
public void saveAll(List<FruitEntity> fruits){
    fruitRepository.saveAll(fruits);
}
إذا قرأت عن SQL ، كما طلبت منك أن تفعل في المرة السابقة، فيجب أن تعلم أن مثل هذه الإجراءات مع قاعدة البيانات يجب تنفيذها باستخدام استعلامات SQL. لكن لا يوجد أي تلميح لذلك في المشروع، وحتى في سجلات وحدة التحكم لا يوجد شيء مماثل. دعنا نعثر عليهم، افتح application.yml، وابحث عن السطر show-sql: هناك (إظهار sql) وقم بتغيير false إلى true. نطلق المشروع وننظر إلى وحدة التحكم، وتمتلئ السجلات بإدخالات جديدة تشبه إلى حد كبير SQL، في الواقع، ليس من الصعب فهم معظمها، على سبيل المثال:
Hibernate: drop table fruit_table if exists //удалить таблицу fruit_table  если она есть
Hibernate: drop table provider_table if exists
Hibernate: create table fruit_table (id_fruit integer not null, fruit_name varchar(255), provider_code integer, primary key (id_fruit))//создать таблицу fruit_table с полями id_fruit тип integer not null, fruit_name  тип varchar(255), provider_code тип integer, назначить первичным ключем поле id_fruit
Hibernate: create table provider_table (id_provider integer not null, provider_name varchar(255), primary key (id_provider))
لكن هذه المدخلة قد تثير الكثير من التساؤلات بسبب علامات الاستفهام التي تحملها:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
دعونا نفكر بشكل منطقي: أولاً، نرى كلمة السبات، مما يعني أن هذا الرجل الكتوم قد وضع مخلبه المكسو بالفراء هنا. بعد القراءة عنه على الإنترنت، علمنا أن السيد هايبر هو تطبيق لنموذج ORM. يصف النموذج العلائقي للكائن العلاقات بين كائنات البرنامج والسجلات في قاعدة البيانات. بعد إصلاح هذه الفكرة، نواصل التفكير بشكل منطقي: من ناحية، لدينا كائن FruitEntity ، وله ثلاثة حقول: Integer id؛ سلسلة اسم الفاكهة؛ رمز موفر عدد صحيح. من ناحية أخرى، لدينا جدول في قاعدة بيانات Fruit_table يحتوي على الحقول id_fruit type integer، نوع Fruit_name varchar(255) ، نوع Provider_code عدد صحيح. بشكل تقريبي، يأخذ Hibernate كائن FruitEntity ، ويسحب قيم حقول الكائن ويكتبها في حقول الجدول المقابلة. لدي سؤال لك: انظر، في فئة InitiateUtils قمنا بتنفيذ ملء جدول الفاكهة، ولكن لسبب ما قمنا بتعيين القيمة على حقلين فقط، أين هو الثالث؟
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
أنا متأكد من أنك ستكتشف ذلك بنفسك، بالإضافة إلى أننا تطرقنا لفترة وجيزة إلى هذه المشكلة في المقالة قبل الأخيرة. أولا، اكتشف أي مجال غير موجود هنا، وبعد ذلك سوف تفهم كل شيء. حسنًا، أحسنت، لقد أنشأ Hiber مجموعة من الطلبات لنا. لكننا لسنا عمياء، فلننفذ بعض الأساليب الإضافية من واجهة JpaRepository<> في فئة FruitService
//возвращает запись из таблицы по id
public Optional<FruitEntity> getById(Integer id){
   return fruitRepository.findById(id);
}

//удаляет запись из таблицы по id
public void delById(Integer id){
    fruitRepository.deleteById(id);
}

//возвращает true or false при поиске в таблице Фруктов an object который соответствует типу FruitEntity or принадлежит к типу an object который наследуется от FruitEntity
public Boolean exist(Example<? extends FruitEntity> example){
    return fruitRepository.exists(example);
}
قم بتنفيذ نفس الأساليب في فئة ProviderService. ثم استخدمها في فئة InitiateUtils لـ FruitEntity و ProviderEntity واطبع النتيجة على وحدة التحكم. (بالمناسبة، إذا كنت لا تعرف، يمكنك كتابة "System.out.println()" بسرعة عن طريق كتابة sout والضغط على Enter، نفس الشيء يعمل مع "public static void main(String[] args){} "فقط اكتب psvm وها أنت ذا وما إلى ذلك ). أعتقد أنك قمت بذلك بالفعل ونحن على استعداد للمضي قدمًا. دعنا نذهب إلى واجهة FruitRepository ونبدأ في الكتابة فيها (أي الكتابة وليس النسخ) بالطريقة التالية: List<FruitEntity> f يجب أن تحصل على الشيء التالي، الربيع ليس مخيفًا، أو كيفية طرح سؤال في قاعدة البيانات - 2 فقط اتصل بالطريقة كما لو كنت تقوم بإنشاء استعلام: findById(Integer id) ) - يجد كائنًا عن طريق المعرف؛ countFruitEntityByFruitName(String name) - سيحسب عدد الفواكه التي تحمل اسمًا محددًا؛ هذه هي الاستعلامات التي تم إنشاؤها بواسطة اسم الطريقة؛ تأكد من قراءتها وتنفيذ الطريقة بين (Integer from، Integer to) في فئة FruitService للبحث في List<FruitEntity> بقيم حقل Provider_code المضمن في فترة زمنية معينة، وعرض نتيجة العمل في وحدة التحكم. على سبيل المثال: ابحث عن جميع الفواكه التي يتراوح رقم موردها بين 5 و7. لا تتعجل في القراءة أكثر حتى تنفذ الطريقة، فلن يستغرق الأمر وقتا طويلا. ربما تكون قد قرأت في المقالة حول الاستعلامات حسب اسم الطريقة: "لا يمكنك كتابة جميع الاستعلامات بهذه الطريقة، ولكن يمكن كتابة الاستعلامات البسيطة". بالنسبة للاستعلامات الأكثر تعقيدًا، يتم استخدام التعليق التوضيحي @Query ويتم استخدام JPQL بدلاً من SQL (لاحظ أيضًا هذه المقالة). بالنسبة لمشروعنا، يمكنك إجراء استعلامات JOIN، مثل هذا:
package ru.java.rush.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import ru.java.rush.entities.FruitEntity;

import java.util.List;

@Repository
public interface FruitRepository extends JpaRepository<FruitEntity,Integer> {

    @Query("select f.fruitName, p.providerName from  FruitEntity f left join ProviderEntity p on f.providerCode = p.id")
    List<String> joinSting();

}
سيكون استعلام SQL القياسي كما يلي: "اختر Fruit_table.fruit_name، Provider_table.provider_name من Fruit_table، انضم إلى Provide_table على Fruit_table.provider_code = Provider_table.id". هنا يمكنك بسهولة إنشاء مراسلات: f ruit_table هو FruitEntiy f، حيث FruitEntiy هو نوع المتغير، وf هو اسمه، أي أن SQL يعمل مع الجداول والحقول، وJPQL مع الكائنات وحقولها. مرة أخرى، Fruit_table.fruit_name هو f.fruitName ؛ نظرًا لأننا نعمل مع الكائنات، فيمكننا إخراج الكائن: فلنكتب طريقة FruitRepository أخرى
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
دعونا ننفذ كلتا الطريقتين في فئة FruitService
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
لا يبدو الأمر سيئًا، لكنهم ما زالوا يستخدمون لغة SQL القديمة الجيدة للاستعلامات المعقدة
@Query(
        value = "select fruit_table.fruit_name, provider_table.provider_name from  fruit_table  join provider_table on fruit_table.provider_code = provider_table.id_provider",  //по идее эту портянку надо засунуть в Howой нибудь  Enum
        nativeQuery = true) //нужно только пометить только nativeQuery = true
ListList<String> joinSqlFruit();
ونحن نستخدمها جميعًا في فئة InitiateUtils
System.out.println("\nТаблица фруктов и их поставщиков");
for (String join : fruitService.joinString()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
for (FruitEntity join : fruitService.joinFruit()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
        for (String join : fruitService.joinSqlFruit()) {
            System.out.println(join);
        }
نطلق المشروع ونرى سجلات جديدة في وحدة التحكم: جدول الفواكه ومورديها Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,جدول الفواكه الفارغة وملحقاتها الموردين FruitEntity(id= 2, FruitName=Fruit2,providerCode=5) FruitEntity(id=3, FruitName=Fruit3,providerCode=2) FruitEntity(id=4, FruitName=Fruit4,providerCode=5) جدول الفواكه ومورديها Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 نعم، إذا كنت قد سئمت بالفعل من "الزائفة" واستعلامات SQL فقط في وحدة التحكم، فيمكنك إرجاع خطأ في مكانه في ملف yaml. ستكتشف سبب وجود قيمة فارغة في الجدول الأول إذا قرأت عن JOIN SQL . وبذلك نكون قد انتهينا من الاستعلامات إلى قاعدة البيانات، وأنا متأكد من أنه لا يزال لديك العديد من الأسئلة، ولكن أتمنى أن تبحث عن إجابات لها، حاولت تسليط الضوء على مسارات البحث. دعونا نحاول تلخيص كل ما تعلمناه خلال هذا الوقت: 1. يمكنك تشغيل خادم ويب في الربيع وهذا ليس بالأمر الصعب. 2. لفهم كيفية عمل كل شيء، عليك أن تغوص في النظرية. حول الكتاب مقال عن الربيع مقال عن الأشياء المفيدة 3. لكي يتحول الفهم إلى كود مادي، تحتاج إلى البرمجة، وقبل المضي قدمًا، ضع يديك على مشاريع بسيطة في Spring-Boot. ومن الأفضل عدم نسخ الكود المكتوب، بل إعادة كتابته. سأقوم بنشر المشروع الذي كنا نعمل عليه أنا وأنت هنا، لكنني سأعتمد على وعيك وأنا متأكد من أنك لن تقوم بالنسخ واللصق دون قصد. رابط مستودع git clone https://FromJava@bitbucket.org/FromJava/jd.git لمن لا يعرف كيفية استخدام هذا الرابط أوصي بتنفيذ مشروعين تدريبيين: مشروع حول طلاء السيارات: الدرجة الأولى: CarEntity{ Integer بطاقة تعريف؛ اسم نموذج السلسلة؛ لون السلسلة؛ } الفئة الثانية: ColorEntity{ معرف عدد صحيح؛ لون السلسلة؛ سعر صحيح؛ } املأ قاعدة البيانات (ابتكر أسماء واقعية حتى يكون من الأسهل فهمها)، وقم بتنفيذ: والكيان والمستودعات والخدمات وإنشاء استعلامات قياسية وعبر الجداول (ما هي تكلفة طلاء سيارة BMW باللون الأحمر؟ ما هو اللون؟ "الأغلى؟ كتابة النماذج على وحدة التحكم بالترتيب الأبجدي وما إلى ذلك)؛ مشروع المكتبة: الدرجة الأولى: BookEntity{ معرف صحيح؛ سلسلة اسم الكتاب؛ عدد صحيح yearCreat؛ معرف تلقائي صحيح؛ } الفئة الثانية: AutorEntity{ معرف عدد صحيح؛ String firstNameAutor; سلسلة LastNameAutor؛ } املأ قاعدة البيانات (ابتكر أسماء واقعية حتى يكون من الأسهل فهمها)، ونفذ: الكيان، والمستودعات، والخدمات، وقم بإنشاء استعلامات قياسية وبين الجداول (من كتب أي كتاب؟ أي كتاب كتب أولاً؟ ما هي الكتب التي تمت كتابتها؟ من 1800 إلى 1900؟ أي من المؤلفين كتب أكبر عدد من الكتب؟) أمثلة لملء قاعدة بيانات مشروع "المكتبة". جدول الكتب BookEntity(id=1, nameBook=Woe from Wit, yearCreat=1824, AuthorId=1) BookEntity(id=2, nameBook=War and Peace, yearCreat=1863, AuthorId=2) BookEntity(id=3, nameBook= Mtsyri، yearCreat=1838، AuthorId=3) BookEntity(id=4, nameBook=Eugene Onegin, yearCreat=1833, AuthorId=4) جدول المؤلف AuthorEntity(id=1, firstNameAuthor=Alexander, lastNameAuthor=Griboyedov) AuthorEntity(id=2) ، firstNameAuthor=Lev, lastNameAuthor=Tolstoy) AuthorEntity(id=3, firstNameAuthor=Mikhail, lastNameAuthor=Lermontov) AuthorEntity(id=4, firstNameAuthor=Alexander, lastNameAuthor=Pushkin) حظًا سعيدًا للجميع، نراكم مرة أخرى!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION