我在使用 Spring data JPA 规范获取列表实体类别时遇到问题。我需要获取所有类别及其食谱,其中
Recipe.dateModified
大于某个日期。我不知道如何创建我的谓词,它只会在每个类别中填充 Collection<Recipe>
那些大于此日期的食谱。
@Entity
public class Category {
private int id;
private String name;
@OneToMany(mappedBy = "categories")
private Collection<Recipe> recipes;
}
@Entity
public class Recipe {
private int id;
private String name;
private Timestamp dateModified;
}
在
CategoryService
我得到 List<Category>
使用规范:
@Service
public class CategoryService {
@Autowired
private CategoryRepository categoryRepository;
public List<Category> findAll(Date date) {
return categoryRepository.findAll(where(byDateModified(date)));
}
}
我会这样写规范,但这不起作用。
public class RecipeSpec {
public static Specification<Category> byDateModified(Date date) {
return (root, query, builder) -> {
final Join<Category, Recipe> recipe = root.join(Category_.recipes, JoinType.LEFT);
return builder.greaterThan(recipe.get(Recipe_.dateModified), date);
};
}
}
在您的 CategoryRepository 实现类中,添加此方法
public Category findAll(Date dateModified) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Category> query = builder.createQuery(Category.class);
Root<Category> category = query.from(Category.class);
ParameterExpression<Date> dateParam = builder.parameter(Date.class);
query.select(category).where(builder.greaterThan(category.get(Category_.recipes).get(Recipe_.dateModified), dateParam));
return em.createQuery(query)
.setParameter(dateParam, dateModified)
.getSingleResult();
}
上面的代码中使用了MetaModel类。如果没有生成元模型类,请在 pom 文件中添加此插件以自动生成元模型类..
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.2.4</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.2.2.Final</version>
</dependency>
</dependencies>
</plugin>
试试这个:
public class RecipeSpec {
public static Specification<Category> byDateModified(Date date) {
return new Specification<Category>() {
public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
final Path<Collection<Recipe>> recipes = root.get(Recipe_.recipes);
final Path<Date> dateModified = recipes.get(Recipe_.dateModified);
return builder.greaterThan(dateModified, date);
};
}
还要确保您的实体映射正确:
-您正在使用mappedby,但关联是单向的!
-集合必须初始化。
-使用日期(而不是时间戳)并添加@Temporal注释!
@Entity
public class Category {
private int id;
private String name;
//@OneToMany(mappedBy = "categories")
@OneToMany
@JoinColumn(name="categoryId")
private Collection<Recipe> recipes = new ArrayList<Recipe>();
}
@Entity
public class Recipe {
private int id;
private String name;
@Temporal(TemporalType.TIMESTAMP)
private Date dateModified;
}