在使用JPA做查询的时候,有时候要把实体对应的所有关联项都查询出来。下面的SellerListing实体中。"specificationConfigs","listingDocs"都是集合。使用@EntityGraph生成的sql语句全是LEFT OUTER JOIN。如果"specificationConfigs"有4条,"listingDocs"有3条,那查询出的数据就是3*4 = 12条。并且查询出的listingDocs、specificationConfigs会有重复的数据。
@EntityGraph(attributePaths = {"product","productSpec","specificationConfigs","listingDocs"})
@Query("SELECT DISTINCT listing FROM SellerListing listing WHERE listing.id=:id")
SellerListing findWithDetailsById(@Param("id") Long id);
解决方法:参考
这里
。和
这里
。
要去除这些重复数据,使用数据库是不明智的。所有只有查询出来后在java程序中去除,我这里把属性声明为LinkedHashSet,并且重写ListingDoc实体的hashCode和equals方法。利用set集合不能放重复对象的属性。把重复数据去除掉。
@OneToMany(mappedBy="listing",fetch=FetchType.LAZY)
private Set<ListingDoc> listingDocs = new LinkedHashSet<ListingDoc>();
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof BaseEntity))
return false;
BaseEntity target = (BaseEntity) obj;
if(this.getId() == null || target.getId() == null)
return false;
return this.getId().equals(target.getId());
public int hashCode() {
return id == null ? 0 : id.hashCode();
特别注意:
如果查询出的是集合,并且要分页查询的时候。这种方式就有问题。因为分页是按照数据库数据分页的。查询出来再过滤,必然导致分页混乱。
@EntityGraph(attributePaths = {"product","productSpec","specificationConfigs","listingDocs"})
@Query("SELECT DISTINCT listing FROM SellerListing listing WHERE listing.title=:title")
List<SellerListing> findWithDetailsByTitle(@Param("title") String title, Pageable pageable);