Spring 用于过滤与子实体的一对多关系的 JPA 规范
Spring JPA Specification to filter one to many relation with child entity
我有如下实体 InwardInventory
@Entity
@Table(name = "inward_inventory")
public class InwardInventory extends ReusableFields
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long in_inventoryId;
@ManyToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JoinTable(name = "inventory_entry", joinColumns = {
@JoinColumn(name = "in_inventoryId", referencedColumnName = "in_inventoryId") }, inverseJoinColumns = {
@JoinColumn(name = "entryId", referencedColumnName = "entryId") })
Set<InwardOutwardList> inwardOutwardList = new HashSet<>();;
//many other fields
}
实体 InwardOutwardList 具有 productId 和数量等字段。
@Entity
@Table(name = "inward_outward_entries")
@Audited
@Where(clause = ReusableFields.SOFT_DELETED_CLAUSE)
public class InwardOutwardList extends ReusableFields
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long entryid;
@ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
@JoinColumn(name="productId",nullable=false)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Product product;
Float quantity;
//other fields and getter setters
}
我想编写一个规范来过滤基于 inwardinventory 的产品 ID。示例 - 如果我将 productId 作为 100 传递,它应该 return 所有包含产品 100 条目的 inwardinventory 列表。有人可以帮助我如何编写我们必须查询列表或实体集的规范。
我能够使用联接实现此目的。下面是代码
库存规格代码
public static Specification<InwardInventory> getSpecification(FilterDataList filterDataList) throws ParseException
{
List<String> productNames = SpecificationsBuilder.fetchValueFromFilterList(filterDataList,"productNames");
Specification<InwardInventory> finalSpec = null;
if(productNames != null && productNames.size()>0)
finalSpec = specbldr.specAndCondition(finalSpec,specbldr.whereChildFieldListContains(
InwardInventory_.INWARD_OUTWARD_LIST,InwardOutwardList_.PRODUCT,Product_.PRODUCT_NAME,productNames));
return finalSpec;
}
以下是通用方法的实现代码,可用于任何具有类似过滤要求class的实体
public Specification<T> whereChildFieldListContains(String childTableName, String gcTable,String fieldName, List<String> names)
{
Specification<T> finalSpec = null;
for(String name:names)
{
Specification<T> finalSpec = (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb)
-> cb.like(root.join(childTableName).join(gcTable).get(fieldName), "%"+name+"%" );
}
return finalSpec;
我有如下实体 InwardInventory
@Entity
@Table(name = "inward_inventory")
public class InwardInventory extends ReusableFields
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long in_inventoryId;
@ManyToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JoinTable(name = "inventory_entry", joinColumns = {
@JoinColumn(name = "in_inventoryId", referencedColumnName = "in_inventoryId") }, inverseJoinColumns = {
@JoinColumn(name = "entryId", referencedColumnName = "entryId") })
Set<InwardOutwardList> inwardOutwardList = new HashSet<>();;
//many other fields
}
实体 InwardOutwardList 具有 productId 和数量等字段。
@Entity
@Table(name = "inward_outward_entries")
@Audited
@Where(clause = ReusableFields.SOFT_DELETED_CLAUSE)
public class InwardOutwardList extends ReusableFields
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long entryid;
@ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
@JoinColumn(name="productId",nullable=false)
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Product product;
Float quantity;
//other fields and getter setters
}
我想编写一个规范来过滤基于 inwardinventory 的产品 ID。示例 - 如果我将 productId 作为 100 传递,它应该 return 所有包含产品 100 条目的 inwardinventory 列表。有人可以帮助我如何编写我们必须查询列表或实体集的规范。
我能够使用联接实现此目的。下面是代码
库存规格代码
public static Specification<InwardInventory> getSpecification(FilterDataList filterDataList) throws ParseException
{
List<String> productNames = SpecificationsBuilder.fetchValueFromFilterList(filterDataList,"productNames");
Specification<InwardInventory> finalSpec = null;
if(productNames != null && productNames.size()>0)
finalSpec = specbldr.specAndCondition(finalSpec,specbldr.whereChildFieldListContains(
InwardInventory_.INWARD_OUTWARD_LIST,InwardOutwardList_.PRODUCT,Product_.PRODUCT_NAME,productNames));
return finalSpec;
}
以下是通用方法的实现代码,可用于任何具有类似过滤要求class的实体
public Specification<T> whereChildFieldListContains(String childTableName, String gcTable,String fieldName, List<String> names)
{
Specification<T> finalSpec = null;
for(String name:names)
{
Specification<T> finalSpec = (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb)
-> cb.like(root.join(childTableName).join(gcTable).get(fieldName), "%"+name+"%" );
}
return finalSpec;