【问题标题】:Spring Jpa Specification, Many to Many, filter by lang and valueSpring Jpa 规范,多对多,按语言和值过滤
【发布时间】:2021-11-15 03:46:57
【问题描述】:

我只想找到 by lang = "en" 和类似 "pom" 的值(pomme 是苹果的法语翻译)。

获取的值将是:

FoodEntity : {
  names : [
    pomme, apple
  ]
}

从技术上讲,它不应该被检索,因为它是 lang = "fr" 。 它没有考虑 lang 谓词。有人有什么想法吗? 它还检索所有名称。我只需要一个!

在@Query 中一切正常,但我需要 Jpa 规范

@Query(value = "select f from FoodEntity f join fetch f.names fn 
where fn.value = ?1 and fn.lang = ?2")



@Entity
@Data
@Table(name = "food")
public class FoodEntity {

@Id
@SequenceGenerator(name = "food_id_seq", sequenceName = "food_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "food_id_seq")
@Column(name = "id")
private Integer id;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "food_name_locale", joinColumns = {@JoinColumn(name = "food_id")}, inverseJoinColumns = {@JoinColumn(name = "locale_id")})
@JsonManagedReference
private Set<LocaleEntity> names = new HashSet<>();
}



public class LocaleEntity {
@Id
@SequenceGenerator(name = "locale_id_seq", sequenceName = "locale_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "locale_id_seq")
@Column(name = "id")
private Integer id;

@Column(name = "value", columnDefinition = "TEXT")
private String value;

@Column(name = "lang")
private String lang;

@ManyToMany(mappedBy = "names")
@JsonBackReference
private Set<FoodEntity> foods;

}

JPA 规范内部:

public class FoodSpecification implements Specification<FoodEntity> {

    private FoodCriteria searchCriteria;

    public FoodSpecification(FoodCriteria searchCriteria) {
        this.searchCriteria = searchCriteria;
    }


    @Override
    public Specification<FoodEntity> and(Specification<FoodEntity> other) {
        return Specification.super.and(other);
    }

    @Override
    public Specification<FoodEntity> or(Specification<FoodEntity> other) {
        return Specification.super.or(other);
    }

    @Override
    public Predicate toPredicate(Root<FoodEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        List<Predicate> predicates = new ArrayList<Predicate>();

        if(searchCriteria.getName() != null && !searchCriteria.getName().isEmpty()){
            predicates.add(criteriaBuilder.and(criteriaBuilder.like(joinFoodName(root).get("value"), searchCriteria.getName() +"%"), criteriaBuilder.equal(joinFoodName(root).get("lang"), searchCriteria.getLang())));

        }
        return criteriaQuery.distinct(true).where(predicates.toArray(new Predicate[] {})).getRestriction();
    }

    private SetJoin<FoodEntity, LocaleEntity> joinFoodName(Root<FoodEntity> root){
        return root.joinSet("names", JoinType.INNER);
    }
}

【问题讨论】:

    标签: spring-boot jpa spring-data-jpa criteria-api openjpa


    【解决方案1】:

    我找到了按值和语言检索的解决方案。

    我的错误是调用了两次方法:

    joinFoodName();
    

    通过这样做,我创建了一个完全独立的辅助内部连接。

    关于获取所有 LocaleEntities 的事实,我暂时没有找到 JPA 规范的任何解决方案。

    【讨论】:

      猜你喜欢
      • 2017-10-28
      • 2020-08-10
      • 2017-08-19
      • 2015-10-28
      • 2018-05-07
      • 2017-01-09
      • 2019-12-07
      • 1970-01-01
      • 2021-09-07
      相关资源
      最近更新 更多