如何使用JPA规范向查询添加独特的属性 [英] How to add distinct property to query with jpa specification
问题描述
我正在使用jhipster标准和jpa规范来实现进行研究的端点。
I am using jhipster criteria and jpa specification to implement an endpoint for making research.
工作正常,但是请始终向我发送副本。
Well it is working, but keep sending me duplicates.
有该模型的Prestation
There is prestations with this model
public class Prestation extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Column(name = "jhi_label", nullable = false)
private String label;
@Column(name = "description")
private String description;
@Column(name = "unit")
private String unit;
@NotNull
@Column(name = "activated", nullable = false)
private boolean activated;
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("prestations")
private SubCategory subCategory;
@OneToMany(mappedBy = "prestation", cascade = CascadeType.ALL, orphanRemoval = true)
private List<CompanyPrestation> companies = new ArrayList<>();
公司与站点间的关系
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<CompanyPrestation> prestations = new ArrayList<>();
这是我用来创建提供给存储库的规范的CompanySpecification类
And here is the CompanySpecification class that i used to create specification that i give to the repository
public class CompanySpecification extends QueryService<Company> implements Specification<Company> {
private static final long serialVersionUID = 1L;
private CompanyCriteria criteria;
public CompanySpecification(CompanyCriteria criteria) {
this.criteria = criteria;
}
@Override
public Predicate toPredicate(Root<Company> roots, CriteriaQuery<?> query, CriteriaBuilder builder) {
Specification<Company> specification = Specification.where(null);
if (criteria != null) {
if (criteria.getName() != null) {
specification = specification.or(buildStringSpecification(criteria.getName(), Company_.name));
}
if (criteria.getSiret() != null) {
specification = specification.or(buildStringSpecification(criteria.getSiret(), Company_.siret));
}
if (criteria.getCodeAPE() != null) {
specification = specification.or(buildStringSpecification(criteria.getCodeAPE(), Company_.codeAPE));
}
if (criteria.getLegalForm() != null) {
specification = specification.or(buildStringSpecification(criteria.getLegalForm(), Company_.legalForm));
}
if (criteria.getVille() != null) {
specification = specification
.and(buildReferringEntitySpecification(criteria.getVille(), Company_.address, Address_.ville));
}
if (criteria.getExercicePlace() != null && !criteria.getExercicePlace().getIn().isEmpty()) {
Filter<ExercicePlace> exercicePlaceFilter = new Filter<>();
exercicePlaceFilter.setIn(criteria.getExercicePlace().getIn().stream().map(ExercicePlace::valueOf)
.collect(Collectors.toList()));
specification = specification.and(buildSpecification(exercicePlaceFilter, Company_.exercicePlace));
}
if (criteria.getCodePostal() != null) {
specification = specification.and(buildReferringEntitySpecification(criteria.getCodePostal(),
Company_.address, Address_.codePostal));
}
if (criteria.getPrestationsId() != null) {
specification = specification.and(buildSpecification(criteria.getPrestationsId(),
root -> root.join(Company_.prestations, JoinType.LEFT)
.join(CompanyPrestation_.prestation, JoinType.LEFT).get(Prestation_.id)));
}
if (criteria.getCatId() != null) {
specification = specification.and(buildSpecification(criteria.getCatId(),
root -> root.join(Company_.prestations, JoinType.LEFT)
.join(CompanyPrestation_.prestation, JoinType.LEFT)
.join(Prestation_.subCategory, JoinType.LEFT).join(SubCategory_.category, JoinType.LEFT)
.get(Category_.id)));
}
if (criteria.getSubCatId() != null) {
specification = specification.and(buildSpecification(criteria.getSubCatId(),
root -> root.join(Company_.prestations, JoinType.LEFT)
.join(CompanyPrestation_.prestation, JoinType.LEFT)
.join(Prestation_.subCategory, JoinType.LEFT).get(SubCategory_.id)));
}
if (criteria.getPrestationName() != null) {
specification = specification.or(buildSpecification(criteria.getPrestationName(),
root -> root.join(Company_.prestations, JoinType.LEFT)
.join(CompanyPrestation_.prestation, JoinType.LEFT).get(Prestation_.label)));
}
if (criteria.getPriceMinimum() != null || criteria.getPriceMaximum() != null) {
specification = specification.and((lroot, lquery, lcriteriaBuilder) -> {
ListJoin<Company, CompanyPrestation> joinCompnayToCompanyPrestations = lroot
.join(Company_.prestations, JoinType.LEFT);
if (criteria.getPriceMinimum() != null && criteria.getPriceMaximum() != null) {
return lcriteriaBuilder.between(
joinCompnayToCompanyPrestations.get(CompanyPrestation_.pricePerUnit),
criteria.getPriceMinimum().getGreaterOrEqualThan(),
criteria.getPriceMaximum().getLessOrEqualThan()
);
} else if (criteria.getPriceMinimum() != null) {
return lcriteriaBuilder.greaterThanOrEqualTo(
joinCompnayToCompanyPrestations.get(CompanyPrestation_.pricePerUnit),
criteria.getPriceMinimum().getGreaterOrEqualThan());
} else {
return lcriteriaBuilder.lessThanOrEqualTo(
joinCompnayToCompanyPrestations.get(CompanyPrestation_.pricePerUnit),
criteria.getPriceMaximum().getLessOrEqualThan());
}
});
}
}
return specification.toPredicate(roots, query, builder);
}
这是我使用它的服务方法
And here is my service method using it
@Transactional(readOnly = true)
public Page<CompanyDTO> findByCriteria(CompanyCriteria criteria, Pageable page) {
log.debug("find by criteria : {}, page: {}", criteria, page);
Specification<Company> spec = Specification.where(null);
CompanySpecification specification = new CompanySpecification(criteria);
spec = (Specification<Company>) specification;
Page<Company> vitrinesPage = companyRepository.findAll(spec, page);
List<CompanyDTO> list = companyMapper.toDto(vitrinesPage.getContent());
Page<CompanyDTO> listPage = new PageImpl<>(list, page, vitrinesPage.getTotalElements());
return listPage;
}
我在CriteriaQuery中发现了一个不同的方法,但是我真的不知道如何添加它在我的规范中。
I found a method distinct in CriteriaQuery but i dont really know how to add it in my specification.
请提供一些帮助!
推荐答案
在您的<$ c内$ c> toPredicate 方法,可以吗?
@Override
public Predicate toPredicate(Root<Company> roots, CriteriaQuery<?> query, CriteriaBuilder builder) {
....
query.distinct(true);
return ...;
}
Though what you are trying to do might not be possible, it is said to be a limitation of JPA
您可以尝试执行的操作是删除内部的重复项提取后的代码,或尝试覆盖等于
& hashCode
方法试图破解不同的定义吗?
What you can try to do, is either remove duplicates within the code after fetch, or try to override equals
& hashCode
methods to try to hack the distinct definition maybe?
这篇关于如何使用JPA规范向查询添加独特的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!