首页 > 解决方案 > JPA 标准规范 - 多选与分组返回所有列

问题描述

我正在尝试使用 JPA 规范和标准在表上实现基本分组。我使用了 query.multiselect 并提供了一列。但是,在执行期间,正在构建 SQL 查询以获取所有列。从理论上讲,一切看起来都很好。不知道我哪里出错了。

下面是服务方法

public List<POJO> fetchInwardnventoryGroupByUsingSpec() throws ParseException 
    {
        Specification<InwardInventory> spec = findAllGroupBy();
        List<POJO> iiData = inwardInventoryRepo.findAll(spec);  
        return iiData;
    }
    
    public static Specification<InwardInventory> findAllGroupBy() 
    {
        return new Specification<InwardInventory>()
        {
            @Override
            public Predicate toPredicate(Root<InwardInventory> root, CriteriaQuery<?> query, CriteriaBuilder cb) 
            {
                query.multiselect(root.get(InwardInventory_.VEHICLE_NO),cb.count(root));
                query.groupBy(root.get(InwardInventory_.VEHICLE_NO));
                return query.getRestriction();
            }
        };
    }

下面是hibernate生成的SQL

/* select
        generatedAlias0 
    from
        InwardInventory as generatedAlias0 
    where
        generatedAlias0.warehouse.warehouseName like :param0 
    group by
        generatedAlias0.vehicleNo */ select
            inwardinve0_.inwardid as inwardid1_13_,
            inwardinve0_.created_at as created_2_13_,
            inwardinve0_.is_deleted as is_delet3_13_,
            inwardinve0_.updated_at as updated_4_13_,
            inwardinve0_.additional_info as addition5_13_,
            inwardinve0_.date as date6_13_,
            inwardinve0_.invoice_received as invoice_7_13_,
            inwardinve0_.our_slip_no as our_slip8_13_,
            inwardinve0_.contact_id as contact11_13_,
            inwardinve0_.supplier_slip_no as supplier9_13_,
            inwardinve0_.vehicle_no as vehicle10_13_,
            inwardinve0_.warehouse_id as warehou12_13_ 
        from
            inward_inventory inwardinve0_ cross 
        join
            warehouse warehouse1_ 
        where
            (
                inwardinve0_.is_deleted = 'false'
            ) 
            and inwardinve0_.warehouse_id=warehouse1_.warehouse_id 
            and (
                warehouse1_.warehouse_name like ?
            ) 
        group by
            inwardinve0_.vehicle_no

下面是实体类

@Entity
@Table(name = "inward_inventory")
@Audited
@Where(clause = ReusableFields.SOFT_DELETED_CLAUSE)
public class InwardInventory extends ReusableFields implements Cloneable
{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="inwardid")
    Long inwardid;
    
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd")
    @Column(nullable = false)
    @NonNull
    Date date;
    
    @NonNull
    String vehicleNo;
    
    String supplierSlipNo;
    
    String ourSlipNo;
    
    @ManyToMany(fetch=FetchType.EAGER,cascade = CascadeType.ALL)
    @JoinTable(name = "inwardinventory_entry", joinColumns = {
            @JoinColumn(name = "inwardid", referencedColumnName = "inwardid") }, inverseJoinColumns = {
                    @JoinColumn(name = "entryId", referencedColumnName = "entryId") })
    Set<InwardOutwardList> inwardOutwardList = new HashSet<>();;
    
    @ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name="warehouse_id",nullable=false)
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    Warehouse warehouse;
    
    @ManyToOne(fetch=FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinColumn(name="contactId",nullable=false)
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    Supplier supplier;
    
    String additionalInfo;
    
    @NonNull
    @Column(nullable = false)
    Boolean invoiceReceived;
//getter/setter
}

标签: javaspring-bootspring-mvcspring-data-jpacriteria-api

解决方案


经过几天的努力终于知道这是一个已知问题

https://jira.spring.io/browse/DATAJPA-1532

因此,我通过自动装配实体管理器处理它,然后创建所有必需的谓词和查询。然后调用 getResults() 而不是 findall()

@Autowired
    EntityManager entityManager;
    public List<Model> getResults() throws ParseException 
    {
        CriteriaQuery<Model> query = modelSpecification.getSpecQuery();
        List<Model> allData  = entityManager.createQuery(query).getResultList();
        return allData;
    }

推荐阅读