JavaRush /Java блогу /Random-KY /Жаз коркунучтуу эмес, же маалымат базасына суроо берүү
Павел
Деңгээл

Жаз коркунучтуу эмес, же маалымат базасына суроо берүү

Группада жарыяланган
МАКАЛАЛАР ЦИКЛИНИН МАЗМУНУ Бүгүн биз долбоордун алкагында маалымат базасы менен иштөөнү жыйынтыктап жатабыз. Эгер сиз бардыгын туура кылган болсоңуз, анда сизде төмөнкү көз карандылыктар менен пом болушу керек:
<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 сурамдары менен аткарылышы керек экенин бorшиңиз керек. Бирок долбоордо бул жөнүндө эч кандай кыйытма жок, ал тургай консолдук журналдарда да окшош эч нерсе жок. Келгиле, аларды таап, application.yml ачып, ошол жерден show-sql: сызыгын таап (sql көрсөтүү) жана жалганды чындыкка өзгөртөлү. Биз долбоорду ишке киргизип, консолду карайбыз, журналдар 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 (?, ?, ?)
Келгиле, логикалык жактан ойлонуп көрөлү: Биринчиден, биз Hibernate деген сөздү көрүп жатабыз, бул жашыруун жигиттин түктүү лапанын бул жерге койгонун билдирет. Интернеттен ал жөнүндө окугандан кийин, биз мырза Хибер ORM моделин ишке ашыруу экенин билебиз. Объект-реляциялык модель программалык an objectилер менен маалыматтар базасындагы жазуулардын ортосундагы мамилелерди сүрөттөйт. Бул идеяны оңдоп, биз логикалык ой жүгүртүүнү улантабыз: Бир жагынан, бизде FruitEntity an objectи бар , анын үч талаасы бар: Integer id; String fruitName; Integer providerCode. Башка жагынан алганда, бизде Fruit_table маалымат базасында id_fruit түрү бүтүн, fruit_name түрү varchar(255) , provider_code түрү бүтүн талаалары бар table бар . Болжол менен айтканда, Hibernate FruitEntity an objectисин алып , an objectтин талааларынын маанилерин чыгарып, аларды тиешелүү table талааларына жазат. Менин сизге суроом бар: Караңыз, InitiateUtils классында жемиш tableсын толтурууну ишке ашырдык, бирок эмнегедир биз эки гана талаага маани койдук, үчүнчүсү кайда?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Муну сиз өзүңүз түшүнөсүз деп ишенем, мындан тышкары, биз акыркы макалада бул маселеге кыскача токтолдук. Биринчиден, бул жерде кайсы талаа жок экенин тактаңыз, анан баарын түшүнөсүз. Молодец, Хибер бизге бир топ суроо-талаптарды жаратты. Бирок биз сокур эмеспиз, FruitService классындагы JpaRepository<> интерфейсинен дагы бир нече ыкмаларды ишке ашыралы
//возвращает запись из таблицы по 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 классында ошол эле ыкмаларды ишке ашырыңыз. Андан кийин аларды FruitEntity жана ProviderEntity үчүн InitiateUtils классында колдонуңуз жана натыйжаны консолго басып чыгарыңыз. (Баса, эгер билбесеңиз, sout терип, enter баскычын басып “System.out.println()” деп тез жаза аласыз, ошол эле нерсе “public static void main(String[] args){} менен иштейт. ” жөн гана psvm деп териңиз, ошондо сиз ж.б. ). Менин оюмча, сиз муну эчак эле жасап койдуңуз жана биз мындан ары кетүүгө даярбыз. Келгиле, FruitRepository интерфейсине кирип , аны терип баштайлы (тактап айтканда, терүү жана көчүрүү эмес) төмөнкү ыкма: List<FruitEntity> f Сиз төмөнкү нерсени алышыңыз керек. Жөн гана методду сурам түзүп жаткандай чакырыңыз: findById(Integer id ) - id боюнча an objectти табат; countFruitEntityByFruitName(String name) - белгилүү бир аталыштагы жемиштердин санын эсептейт; Бул ыкманын аталышы менен түзүлгөн сурамдар; алар жөнүндө окуп чыгууну жана FruitService классындагы (Integer from, Integer to) ортосундагы ыкманы ишке ашырууну унутпаңыз , анда List<FruitEntity> ге камтылган провайдер_codeу талаасынын маанилери боюнча издөө керек. белгилүү бир интервал жана консолдо иштин жыйынтыгын көрсөтүү. Мисалы: жеткирүүчүнүн саны 5тен 7ге чейинки бардык жемиштерди табыңыз. Методду ишке ашырмайынча, андан ары окууга шашпаңыз, бул көп убакытты талап кылbyte. Методдун аталышы боюнча сурамдар жөнүндө макалада окуган болушуңуз мүмкүн: "Сиз бардык суроо-талаптарды мындай жаза албайсыз, бирок жөнөкөйлөрдү жазууга болот." Татаал суроолор үчүн @Query annotationсы колдонулат жана SQL ордуна JPQL колдонулат (бул макаланы да эске алыңыз). Биздин долбоор үчүн сиз JOIN сурамдарын жасай аласыз, мисалы: Жаз коркунучтуу эмес, же маалымат базасына суроо берүү - 2
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ден солго кошулуңуз fruit_table.provider_code = provider_table.id". Бул жерден корреспонденцияны оңой түзө аласыз: f ruit_table - FruitEntiy f, мында FruitEntiy - өзгөрмөнүн түрү, f - анын аты, башкача айтканда, SQL tableлар жана талаалар менен, ал эми JPQL - an objectтер жана алардын талаалары менен иштейт. Кайрадан fruit_table.fruit_name f.fruitName ; _ Объекттер менен иштегендиктен, биз an objectти чыгара алабыз: башка 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();
}
Бул жаман угулbyte, бирок алар дагы эле татаал суроолор үчүн жакшы эски 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);
        }
Биз долбоорду ишке киргизип, консолдо жаңы журналдарды көрүп жатабыз: жемиштердин tableсы жана алардын жеткирүүчүлөрү Fruit1, null Fruit2, Provider5 Fruit3, Provider2 Fruit4, Provider5 Fruit5, null Fruit6, null Fruit7, null Fruit8, null Fruit9, null Жемиштер жеткирүүчүлөр 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 файлында анын ордуна false кайтара аласыз. Эмне үчүн биринчи tableда null бар, сиз JOIN SQL жөнүндө окусаңыз билесиз . Ошентип, биз маалымат базасына суроо-талаптар менен бүттү, мен сизде дагы көптөгөн суроолор бар деп ишенем, бирок аларга жооп издейсиз деп үмүттөнөм, мен издөө жолдорун бөлүп көрсөтүүгө аракет кылдым. Келгиле, бул убакыттын ичинде үйрөнгөнүбүздүн баарын кыскача айтып берүүгө аракет кылалы: 1. Жазында веб-serverди иштетсеңиз болот жана бул кыйын эмес. 2. Мунун баары кантип иштээрин түшүнүү үчүн теорияга сүңгүп киришиңиз керек. Китеп жөнүндө Жаз жөнүндө макала Пайдалуу нерселер жөнүндө макала 3. Түшүнүү физикалык codeго айланышы үчүн codeдонуп, андан ары өтүүдөн мурун жазгы жүктөөдөгү жөнөкөй долбоорлорду колго алуу керек. Ал эми жазылган codeду көчүрбөй, кайра жазган жакшы. Мен сиз экөөбүз иштеп жаткан долбоорду бул жерге жайгаштырам, бирок мен сиздин маалымдуулугуңузга таянам жана сиз ойлонбой көчүрүп чаптабайсыз деп ишенем. Гит клон репозиторийине шилтеме https://FromJava@bitbucket.org/FromJava/jd.git Бул шилтемени кантип колдонууну билбегендер үчүн мен эки окуу долбоорун ишке ашырууну сунуштайм: Машиналарды боёо боюнча долбоор: Биринчи класс: CarEntity{ Integer id; String modelName; сап түсү; } Экинчи класс: ColorEntity{ Integer id; сап түсү; бүтүн баа; } Маалымат базасын толтуруңуз (түшүнүү оңой болушу үчүн реалдуу аталыштарды табыңыз), ишке ашырыңыз: , an object, репозиторийлер, кызматтар, стандарттуу жана кайчылаш table сурамдарын түзүңүз (BMWны кызылга боёо канча турат? Кандай түс эң кымбаты?Консолго моделдерди алфавиттик тартипте жазыңыз ж.б.); Китепкана долбоору: Биринчи класс: BookEntity{ Integer id; String nameBook; бүтүн сан yearCreat; Integer autorId; } Экинчи класс: AutorEntity{ Integer id; String firstNameAutor; String lastNameAutor; } Маалымат базасын толтуруңуз (түшүнүү оңой болушу үчүн реалдуу аталыштарды ойлоп табыңыз), ишке ашырыңыз: an object, репозиторийлер, кызматтар, стандарттуу жана tableлар аралык сурамдарды түзүңүз (Ким кайсы китепти жазган? Кайсы китеп биринчи жазылган? Кайсы китептер жазылган? 1800-жылдан 1900-жылга чейин? Authorлордун кайсынысы эң көп китеп жазган?); "Китепкана" долбоорунун маалымат базасын толтуруу үчүн мисалдар Китеп tableсы BookEntity(id=1, nameBook=Wit from Wo, yearCreat=1824, authorId=1) BookEntity(id=2, nameBook=Согуш жана Тынчтык, yearCreat=1863, authorId=2) BookEntity(id=3, nameBook= Mtsyri, yearCreat=1838, authorId=3) BookEntity(id=4, nameBook=Евгений Онегин, yearCreat=1833, authorId=4) Author tableсы AuthorEntity(id=1, firstNameAuthor=Alexander, lastNameAuthor=Griboedov) Aut=2 , firstNameAuthor=Lev, LastNameAuthor=Толстой) AuthorEntity(id=3, firstNameAuthor=Михаил, LastNameAuthor=Лермонтов) AuthorEntity(id=4, firstNameAuthor=Александр, lastNameAuthor=Пушкин) Баарыңарга ийгorк !
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION