Выполнение запросов с использованием класса в Spring

#java #spring-boot #jpa #intellij-idea

#java #весенняя загрузка #jpa #intellij-идея

Вопрос:

я пытаюсь выполнить этот запрос

List<Product> findProductByCategory_CategoryNameAndPriceBetween(String category, double min, double max);

но возвращаемый запрос представляет собой пустой список. Что я делаю не так? Я также пробовал без подчеркивания между категорией и именем категории. Это категория класса и продукт:

 @Entity
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ID")
    private Long id;

    @Column(name = "NAME")
    private String categoryName;
    
    @OneToMany(mappedBy = "category", fetch = FetchType.EAGER)
    private List<Product> products;

...
}
 
 @Entity
@Table(name="PRODUCT")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ID")
    private Long id;

    @Column(name="PRICE")
    private Double price;

    @Column(name="BRAND")
    private String brand;

    @Column(name="MODEL")
    private String model;

    //@Lob
    @Column(name="DESCRIPTION")
    private String description;

    @Column(name = "IMAGE_URL")
    private String imageUrl;

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID", referencedColumnName = "ID")
    private Category category;
 

И вот как я реализовал репозиторий:

 @Repository
public interface ProductDao extends JpaRepository<Product,Long> {
...
 

Комментарии:

1. Пожалуйста, также опубликуйте свой класс JPA!

2. Я нигде не вижу цены. Обратите внимание также, что первым шагом обычно является регистрация ваших операторов SQL , чтобы подтвердить, что они соответствуют ожидаемой логике.

Ответ №1:

С помощью приведенной ниже реализации ваш запрос выполняется просто отлично.

Пожалуйста, обратите внимание, что я добавил альтернативную реализацию:

 List<Product> findByCategoryAndPriceBetween(Category category, double min, double max);
 

Я подозреваю, что когда вы тестируете это, вы не сохраняете никаких продуктов, потому что в вашем коде отсутствует каскадирование внутри Category класса. Следовательно, я добавил свою реализацию, используемую во время тестов.

Категория класс

 package no.mycompany.myapp.misc;

import lombok.Data;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@Entity
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private Long id;

    @Column(name = "NAME")
    private String categoryName;

    @OneToMany(mappedBy = "category", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private List<Product> products = new ArrayList<>();
}
 

Класс продукта

 package no.mycompany.myapp.misc;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

// cannot use @Data here because of circular ref
@Getter
@Setter
@Entity
@Table(name="PRODUCT")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="ID")
    private Long id;

    @Column(name="PRICE")
    private Double price;

    @Column(name="BRAND")
    private String brand;

    @Column(name="MODEL")
    private String model;

    //@Lob
    @Column(name="DESCRIPTION")
    private String description;

    @Column(name = "IMAGE_URL")
    private String imageUrl;

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID", referencedColumnName = "ID")
    private Category category;
}
 

ProductDao

 public interface ProductDao extends JpaRepository<Product, Long> {
    List<Product> findProductByCategory_CategoryNameAndPriceBetween(String category, double min, double max);
    List<Product> findByCategoryAndPriceBetween(Category category, double min, double max);
}
 

Давайте добавим пару тестов по этому поводу:

 package no.mycompany.myapp.misc;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.ActiveProfiles;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

@DataJpaTest
public class ProductDaoTest {

    @Autowired
    ProductDao productDao;

    @Autowired
    TestEntityManager testEntityManager;

    @Test
    public void findByCategoryAndPriceBetween_singleCategoryWithSingleProductInDb_expectSingleProduct() {
        var category = createCategoryWithSingleProduct();
        testEntityManager.persist(category);
        var result = productDao.findByCategoryAndPriceBetween(category, 0.0, 2.0);
        assertThat(result.size()).isEqualTo(1);
    }

    @Test
    public void findByCategoryAndPriceBetween_singleCategoryWithSingleProductInDb_expectEmptyResult() {
        var category = createCategoryWithSingleProduct();
        testEntityManager.persist(category);
        var result = productDao.findByCategoryAndPriceBetween(category, 5.0, 6.0);
        assertThat(result.size()).isEqualTo(0);
    }

    @Test
    public void findProductByCategory_CategoryNameAndPriceBetween_singleCategoryWithSingleProductInDb_expectSingleProduct() {
        var category = createCategoryWithSingleProduct();
        testEntityManager.persist(category);
        var result = productDao.findProductByCategory_CategoryNameAndPriceBetween(category.getCategoryName(), 0.0, 2.0);
        assertThat(result.size()).isEqualTo(1);
    }

    private static Category createCategoryWithSingleProduct() {
        Product product = new Product();
        product.setPrice(1.00);

        Category category = new Category();
        category.setCategoryName("test");
        category.getProducts().add(product);
        product.setCategory(category);

        return category;
    }
}
 

Ответ №2:

Согласно документации, ваш метод должен быть:

 List<Product> findProductByCategoryNameAndPriceBetween(String category, double min, double max)
 

при условии, что CategoryName и price определены в классе Category.

Комментарии:

1. Цена находится внутри класса Product, а CategoryName — внутри класса Category