use*_*379 6 hibernate jpa soft-delete spring-data-jpa spring-boot
有没有办法在中间实体(映射表)中使用@OneToMany和过滤软删除的多对多关联@ManyToOne?
product并且product_option_group是 N:M 关系。我正在使用该disabled_datetime列实现软删除,并希望ProductOptionGroup从Product实体中过滤一个集合。这篇文章正在使用@ManyToMany并@Where实现这一目标。我跟着,它工作(禁用product_option_groups 被过滤)。需要注意@Where的ProductOptionGroup类。
// `product` <-> `product-product_option_group` <-> `product_option_group`
@Entity
@Table(name = "product")
public class Product implements Serializable {
...
@ManyToMany
@JoinTable(name = "product-product_option_group",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "product_option_group_id"))
private final Set<ProductOptionGroup> productOptionGroups = new HashSet<>();
...
}
@Entity
@Table(name = "product_option_group")
@Where(clause = "disabled_datetime is null")
public class ProductOptionGroup implements Serializable {
...
@Column(name = "disabled_datetime")
private ZonedDateTime disabledDatetime;
...
}
Run Code Online (Sandbox Code Playgroud)
但我想用@OneToMany在product-product_option_group桌子上,就像这样。
@Entity
@Table(name = "product")
public class Product implements Serializable {
...
@OneToMany(mappedBy = "id.product")
private final Set<ProductProductOptionGroup> productProductOptionGroups = new HashSet<>();
...
}
@Entity
@Table(name = "`product-product_option_group`")
public class ProductProductOptionGroup implements Serializable {
@EmbeddedId
private final ProductProductOptionGroupId id = new ProductProductOptionGroupId();
...
}
@Embeddable
public class ProductProductOptionGroupId implements Serializable {
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "product_id", referencedColumnName = "id")
private Product product;
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "product_option_group_id", referencedColumnName = "id")
@Where(clause = "disabled_datetime is null")
private ProductOptionGroup productOptionGroup;
}
@Entity
@Table(name = "product_option_group")
@Where(clause = "disabled_datetime is null")
public class ProductOptionGroup implements Serializable {
...
}
Run Code Online (Sandbox Code Playgroud)
但随后@Where注释将不再起作用,因此product_option_group也选择了 disabled s。如何解决这个问题?
我想在等待答案时添加解决方法。
首先,我可以添加一个视图作为过滤器。
CREATE VIEW `product-product_option_group-enabled` AS
SELECT *
FROM `product-product_option_group` ppog
JOIN product_option_group pog ON ppog.product_option_group_id = pog.id
AND pog.disabled_datetime IS NULL;
Run Code Online (Sandbox Code Playgroud)
@Entity
@Table(name = "`product-product_option_group-enabled`") // using the view as a filter
public class ProductProductOptionGroupEnabled implements Serializable {
@EmbeddedId
private final ProductProductOptionGroupId id = new ProductProductOptionGroupId();
...
}
Run Code Online (Sandbox Code Playgroud)
然后用于ProductProductOptionGroupEnabled读取和ProductProductOptionGroup任何数据修改可能会解决问题。我不喜欢这个。
equals()并且hashCode())。也许我可以利用可更新和可插入视图,但我仍然需要ProductProductOptionGroup选择每一行。
其次,我可以从 Java 中过滤集合。
@Entity
@Table(name = "product")
public class Product implements Serializable {
...
@OneToMany(mappedBy = "id.product")
private final Set<ProductProductOptionGroup> productProductOptionGroups = new HashSet<>();
public Set<ProductProductOptionGroup> getProductProductOptionGroups() {
return productProductOptionGroups.stream()
.filter(o -> o.getId().getProductOptionGroup().getDisabledDatetime() == null)
.collect(Collectors.toSet());
}
public Set<ProductProductOptionGroup> getProductProductOptionGroupsAll() {
return productProductOptionGroups;
}
...
}
Run Code Online (Sandbox Code Playgroud)
然后使用getProductProductOptionGroups()来获取过滤后的集合。我也不喜欢这个。
product-product_option_group表中的每一行,而不管disabled_datetime.javax.persistence.EntityNotFoundException: Unable to find with id xxx可能发生。可以通过join fetching 问题实体来解决