使用 Spring Data JPA Repository 中的 EntityGraph 进行过滤
Filtering using EntityGraph in Spring Data JPA Repository
我有一个 Listing
table 与 ListingAttachment
有一对多的关系。现在在整个应用程序中,每个 table/entity 都有 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
相关实体上过滤或应用条件。
例如,在我的例子中,我应该使用 deleteFlag
0 及其所有附件 (ListingAttachments) 获取 Listing
,这反过来也必须有 deleteFlag
0。使用 EntityGraph
如上面的存储库所示,它获取所有附件而不考虑 deleteFlag
。有什么方法可以根据 deleteFlag
过滤附件吗?
EntityGraph 定义实体的哪些属性或(子)图应该被获取(急切地或惰性地),而不必在实体本身上定义它们。
在 JPA 2.0 中(没有 EntityGraph)如果要使用 FetchType.LAZY
(默认)或 FetchType.EAGER
加载关系,则必须在实体处定义,并且始终使用此模式。
使用 EntityGraph 您可以为每个查询定义属性和(子)图。
EntityGraph不用于过滤元素
如果您想找到未标记为已删除 (delete flag = 0
) 且至少有一个 ListingAttachment
未标记为已删除的 Listings
,您可以通过使用 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
,因为您无法使用 listingAttachments
集合在 JPA 查询中直接取消引用 deleteFlag
。
以上示例 return 列出了所有未标记为已删除且至少有一个未标记为已删除的 ListingAttachment 的列表。
如果您想要 return 未标记为已删除但可能没有 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")
我有一个 Listing
table 与 ListingAttachment
有一对多的关系。现在在整个应用程序中,每个 table/entity 都有 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
相关实体上过滤或应用条件。
例如,在我的例子中,我应该使用 deleteFlag
0 及其所有附件 (ListingAttachments) 获取 Listing
,这反过来也必须有 deleteFlag
0。使用 EntityGraph
如上面的存储库所示,它获取所有附件而不考虑 deleteFlag
。有什么方法可以根据 deleteFlag
过滤附件吗?
EntityGraph 定义实体的哪些属性或(子)图应该被获取(急切地或惰性地),而不必在实体本身上定义它们。
在 JPA 2.0 中(没有 EntityGraph)如果要使用 FetchType.LAZY
(默认)或 FetchType.EAGER
加载关系,则必须在实体处定义,并且始终使用此模式。
使用 EntityGraph 您可以为每个查询定义属性和(子)图。
EntityGraph不用于过滤元素
如果您想找到未标记为已删除 (delete flag = 0
) 且至少有一个 ListingAttachment
未标记为已删除的 Listings
,您可以通过使用 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
,因为您无法使用 listingAttachments
集合在 JPA 查询中直接取消引用 deleteFlag
。
以上示例 return 列出了所有未标记为已删除且至少有一个未标记为已删除的 ListingAttachment 的列表。
如果您想要 return 未标记为已删除但可能没有 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")