OneToMany 关系的 Spring Data JPA 规范

问题描述 投票:0回答:2

我在使用 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);
        };
    }

}
java spring hibernate spring-data-jpa criteria-api
2个回答
0
投票

在您的 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>

0
投票

试试这个:

  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;

}
© www.soinside.com 2019 - 2024. All rights reserved.