hibernate Spring Data JPA一对多关系规范

yfwxisqw  于 2023-10-23  发布在  Spring
关注(0)|答案(2)|浏览(148)

我在使用Spring Data JPA规范获取List实体Categories时遇到了问题。我需要得到所有类别与他们的食谱,其中Recipe.dateModified更大,然后一些日期。我不知道如何创建我的 predicate ,这将填补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);
        };
    }

}
w1e3prcc

w1e3prcc1#

在CategoryRepository Implementation类中,添加以下方法

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类在上面的代码中使用。如果没有生成Meta模型类,请在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>
h79rfbju

h79rfbju2#

试试这个:

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);
        };

    }

并确保您的实体Map正确:

  • 您正在使用mappedby,但关联是单向的!
  • 必须初始化集合。
  • 使用Date(而不是timestamp)并添加@Temporal annotation!
@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;

}

相关问题