#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