Sridhar Patnaik
Sridhar Patnaik

Reputation: 1118

Spring JPA Specification to filter one to many relation with child entity

I have an entity InwardInventory as below

@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
}

Entity InwardOutwardList have fields like productId and quantity.

@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
}

I want to write a specification to filter inwardinventory based product id. Example - If I pass productId as 100, it should return all inwardinventory list which has entry for product 100. Can someone help me how to write specification where we have to query list or set of entities.

Upvotes: 1

Views: 7268

Answers (1)

Sridhar Patnaik
Sridhar Patnaik

Reputation: 1118

I was able to achieve this using joins. Below is the code

Code for stock specification


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;
    }

and below is the code for implementation of generic method which can be used for any entity class having similar filter requirement


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;

Upvotes: 4

Related Questions