我有Listing
表与ListingAttachment
有一对多的关系。现在在整个应用程序中,每个表/实体都有deleteFlag
,每个存储库只能使用deleteFlag
0获取数据。所以基本上,我们不会删除任何仅将deleteFlag标记为1的数据。
以下是我的实体结构:
Listing.java
@Entity
public class Listing {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
String title;
String description;
@OneToMany(mappedBy = "listing", cascade={CascadeType.ALL})
private Set<ListingAttachment> listingAttachments;
private int deleteFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(int deleteFlag) {
this.deleteFlag = deleteFlag;
}
public Set<ListingAttachment> getListingAttachments() {
return listingAttachments;
}
public void setListingAttachments(Set<ListingAttachment> listingAttachments) {
this.listingAttachments = listingAttachments;
}
public ListingAttachment addListingAttachment(ListingAttachment listingAttachment) {
getListingAttachments().add(listingAttachment);
listingAttachment.setListing(this);
return listingAttachment;
}
public ListingAttachment removeListingAttachment(ListingAttachment listingAttachment) {
getListingAttachments().remove(listingAttachment);
listingAttachment.setListing(null);
return listingAttachment;
}
}
ListingAttachment.java
@Entity
public class ListingAttachment {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
String fileName;
@ManyToOne
@JoinColumn(name = "LISTING_ID")
private Listing listing;
private int deleteFlag;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Listing getListing() {
return listing;
}
public void setListing(Listing listing) {
this.listing = listing;
}
public int getDeleteFlag() {
return deleteFlag;
}
public void setDeleteFlag(int deleteFlag) {
this.deleteFlag = deleteFlag;
}
}
ListingRepository.java
public interface ListingRepository extends JpaRepository<Listing, Long> {
@EntityGraph(attributePaths = { "listingAttachments" })
@Query("SELECT l FROM Listing l WHERE l.id = (:id) and deleteFlag = 0")
public ListingfindOneWithImagesAndAttachments(@Param("id") Long id);
}
使用EntityGraph,我们可以轻松获取OneToMany实体。但问题是如何在Many
相关实体上过滤或应用条件。
例如,在我的情况下,我应该使用Listing
0及其所有附件(ListingAttachments)获取deleteFlag
,而后者也必须deleteFlag
0。使用{{1}如上面的存储库所示,它提取所有附件而不管EntityGraph
。有什么方法可以根据deleteFlag
过滤附件吗?
答案 0 :(得分:0)
EntityGraph 定义实体的哪些属性或(子)图应该被提取(急切或懒惰),而不必在实体本身上定义它们。
在JPA 2.0(没有EntityGraph)中,您必须在实体中定义是否要使用FetchType.LAZY
(默认值)或FetchType.EAGER
来加载关系,并始终使用此模式。
使用 EntityGraph ,您可以为每个查询定义属性和(子)图。
EntityGraph 不用于过滤元素。
如果您要查找未标记为已删除的Listings
(delete flag = 0
)且至少有一个ListingAttachment
未标记为已删除,则可以使用FETCH JOIN
public interface ListingRepository extends JpaRepository<Listing, Long> {
@EntityGraph(attributePaths = { "listingAttachments" })
@Query("SELECT l FROM Listing l JOIN l.listingAttachments a
WHERE l.id = (:id) and l.deleteFlag = 0 and a.deleteFlag = 0")
public Listing findOneWithImagesAndAttachments(@Param("id") Long id);
}
您需要加入ListingAttachments
,因为您无法使用deleteFlag
集合直接取消引用JPA查询中的listingAttachments
。
上面的示例将返回所有未标记为已删除的列表,并且至少有一个未标记为已删除的ListingAttachment。
如果要返回未标记为已删除但可能没有ListingAttachments的列表,则必须将其更改为LEFT OUTER JOIN
@Query("SELECT l FROM Listing l
LEFT OUTER JOIN l.listingAttachments a
WHERE l.id = (:id) and l.deleteFlag = 0 and a.deleteFlag = 0")