JpaRepository выборка

168
19 октября 2018, 16:10

Три взаимосвязанные сущности: города (City), улицы (Street), жители (People).

Класс Street имеет поле

@ManyToOne
private City parentCity;

Класс People имеет поле

@ManyToOne
private Street parentStreet;

Для того, чтобы выбрать жителей определенной улицы:

public interface PeopleRepo extends JpaRepository<People, Long> {
    List<People> findAllByParentStreet(Street street);
}

Как написать метод выбирающий жителей из определенного города?!

Answer 1

Если Вам недостаточно автоматически сгенерированных методов поиска в репозитории, то Вы всегда можете объявить в репозитории метод поиска и указать запрос, с помощью которого данный поиск и будет производиться. Запрос состовляется с использованием JPA query language.

Данный запрос можно указать либо с помощью аннотации @Query непосредственно над методом поиска, либо с использованием @NamedQuery над классом сущности.

В первом случае решение будет следующим:

public interface PeopleRepository  extends JpaRepository<People, Long> {
    @Query("SELECT p FROM People p JOIN p.parentStreet s WHERE s.parentCity = :city")
    List<People> findAllByCity(@Param("city") City city);
}

Параметры в запрос можно передавать указывая номер соответствующего параметра метода s.parentCity = ?1. Или с помощью именованных параметров. В данном случае перед соответствующим параметром в методе необходимо проставить аннотацию @Param("paramname"), после чего вы можете указывать данный параметр в запросе s.parentCity = :paramname"

Никто вам не мешает искать и по свойствам связанных сущностей:

public interface PeopleRepository  extends JpaRepository<People, Long> {
    @Query("SELECT p FROM People p JOIN p.parentStreet s JOIN s.parentCity c WHERE c.name = :cityname")
    List<People> findAllByCityName(@Param("cityname") String cityname);
}

Во втором случае Вам необходимо указать аннотацию @NamedQuery над классом сущности. Вам необходимо указать имя метода и сам запрос: Ради разнообразия я создал метод поиска людей по названию улицы.

@Entity
@NamedQuery(name = "People.findAllByStreetName", query = "SELECT p FROM People p JOIN p.parentStreet s where s.name = :streetname")
public class People {
    // ...
}

После чего Вам нужно объявить в репозитории одноименный метод:

public interface PeopleRepository  extends JpaRepository<People, Long> {
    List<People> findAllByStreetName(@Param("streetname") String streetname);
}

Всё это можно найти в документации Spring: https://docs.spring.io/spring-data/jpa/docs/1.5.0.RC1/reference/html/jpa.repositories.html

Ниже представлен полноценный рабочий пример.

Класс City:

package com.stackoverflow.ru.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class City {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String name;
    public City() { }
    public City(String name) {
        this.name = name;
    }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    @Override
    public String toString() {
        return name;
    }
}

Класс People:

package com.stackoverflow.ru.model;
import javax.persistence.*;
@Entity
@NamedQuery(name = "People.findAllByStreetName", query = "SELECT p FROM People p JOIN p.parentStreet s where s.name = :streetname")
public class People {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String secondName;
    @ManyToOne
    private Street parentStreet;
    public People() { }
    public People(String firstName, String secondName, Street parentStreet) {
        this.firstName = firstName;
        this.secondName = secondName;
        this.parentStreet = parentStreet;
    }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getSecondName() { return secondName; }
    public void setSecondName(String secondName) { this.secondName = secondName; }
    public Street getParentStreet() { return parentStreet; }
    public void setParentStreet(Street parentStreet) { this.parentStreet = parentStreet; }
    @Override
    public String toString() {
        return firstName + ' ' + secondName + " from " + parentStreet;
    }
}

Класс Street:

package com.stackoverflow.ru.model;
import javax.persistence.*;
@Entity
public class Street {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private Long id;
    private String name;
    @ManyToOne
    private City parentCity;
    public Street() { }
    public Street(String name, City parentCity) {
        this.name = name;
        this.parentCity = parentCity;
    }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public City getParentCity() { return parentCity; }
    public void setParentCity(City parentCity) { this.parentCity = parentCity; }
    @Override
    public String toString() {
        return name + ", " + parentCity;
    }
}

Интерфейс CityRepository:

package com.stackoverflow.ru.repository;
import com.stackoverflow.ru.model.City;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CityRepository extends JpaRepository<City, Long> {
    City findByName(String name);
}

Интерфейс PeopleRepository:

package com.stackoverflow.ru.repository;
import com.stackoverflow.ru.model.City;
import com.stackoverflow.ru.model.People;
import com.stackoverflow.ru.model.Street;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface PeopleRepository  extends JpaRepository<People, Long> {
    List<People> findAllByParentStreet(Street street);
    @Query("SELECT p FROM People p JOIN p.parentStreet s WHERE s.parentCity = :city")
    List<People> findAllByCity(@Param("city") City city);
    @Query("SELECT p FROM People p JOIN p.parentStreet s JOIN s.parentCity c WHERE c.name = :cityname")
    List<People> findAllByCityName(@Param("cityname") String cityname);
    List<People> findAllByStreetName(@Param("streetname") String streetname);
}

Класс Application:

package com.stackoverflow.ru;
import com.stackoverflow.ru.model.City;
import com.stackoverflow.ru.model.People;
import com.stackoverflow.ru.model.Street;
import com.stackoverflow.ru.repository.CityRepository;
import com.stackoverflow.ru.repository.PeopleRepository;
import com.stackoverflow.ru.repository.StreetRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import java.util.Arrays;
import java.util.List;
@SpringBootApplication
public class Application {
    @Autowired
    CityRepository cityRepository;
    @Autowired
    StreetRepository streetRepository;
    @Autowired
    PeopleRepository peopleRepository;
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
    @Bean("dataInitialization")
    CommandLineRunner init() {
        return (args) -> {
            City moscow = new City("Moscow");
            City piter = new City("Saint-Petersburg");
            cityRepository.save(Arrays.asList(moscow,piter));
            Street tverskaya = new Street("Tverskaya-Yamskaya street", moscow);
            Street ordynka = new Street("Ordynka street", moscow);
            Street nevskaya = new Street("Nevskaya street", piter);
            streetRepository.save(Arrays.asList(tverskaya, ordynka, nevskaya));
            People sergey = new People("Sergey", "Jdanov", tverskaya);
            People alena = new People("Alena", "Zaharova", tverskaya);
            People maxim = new People("Maksim", "Stukov", ordynka);
            People maria = new People("Maria", "Danilenko", nevskaya);
            People pavel = new People("Pavel", "Morozov", nevskaya);
            peopleRepository.save(Arrays.asList(sergey, alena, maxim, maria, pavel));
            System.out.println("initialization complete");
        };
    }
    @Bean()
    @DependsOn({"dataInitialization"})
    CommandLineRunner test() {
        return (args) -> {
            City moscow = cityRepository.findByName("Moscow");
            List<People> peopleFromMoscow = peopleRepository.findAllByCity(moscow);
            List<People> peopleFromSaintPetersburg = peopleRepository.findAllByCityName("Saint-Petersburg");
            List<People> peopleFromTverskaya = peopleRepository.findAllByStreetName("Tverskaya-Yamskaya street");
            System.out.println("\n:::::         PEOPLE FROM MOSCOW          ::::: ");
            peopleFromMoscow.forEach( (people) -> { System.out.println(people); } );
            System.out.println("\n:::::    PEOPLE FROM SAINT-PETERSBURG     ::::: ");
            peopleFromSaintPetersburg.forEach( (people) -> { System.out.println(people); } );
            System.out.println("\n:::::    PEOPLE FROM TVERSKAYA STREET     ::::: ");
            peopleFromTverskaya.forEach( (people) -> { System.out.println(people); } );
            peopleRepository.deleteAll();
            streetRepository.deleteAll();
            cityRepository.deleteAll();
        };
    }
}

Результат запуска:

PS: Однострочные геттеры/сеттеры и лямбды при выводе использовал ради краткости.

READ ALSO
Конкретное разрешение для media

Конкретное разрешение для media

Как в правиле @media указывать конкретное разрешение,а не только ширину окна? Хочу адаптировать для отдельных девайсов,но не могу понять как

157
Адаптивные ряды и строки в CSS

Адаптивные ряды и строки в CSS

На большом экране у меня должно 6 элеметов в ряд, а на мобильных экранах по одному элементу, но выводится по другомуКак мне исправить данный...

146
Не скролится по ссылке в лендинге

Не скролится по ссылке в лендинге

Сделал менюшку в шапке, создал обычные ссылки которые ссылаются к id блоку, но при нажатии скролл не срабатывает и оно просто листается в самый...

138