使用CriteriaBuilder创建Hibernat查询,包括Java中的Join,Group By和Count

时间:2019-06-28 10:39:05

标签: java hibernate jpa

在Java程序中,我有两个实体InvoiceCategory(例如保险,薪水,汽车等)。每个Invoice恰好属于一个Category。现在,我想显示一个表,其中列出了所有现有类别以及实际用于发票的次数。像这样:

enter image description here

SQL看起来像这样:

select categories.name, categories.id, count(invoice.id) as usages 
  from categories 
  left join invoice on categories.id = invoice.category_id 
  group by categories.id

由于我刚接触Hibernate,所以我学习了官方文档,但是该文档仅显示基于Person and Address关系的示例。但是,在我的情况下,类别没有直接链接到发票(反之亦然:每张发票都有一个类别ID)。因此,我试用了这些代码,并提出了以下源代码。显然有一个严重的缺点,因为我没有发票就无法获得类别:

    CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
    CriteriaQuery<CategoryWrapper> criteria = criteriaBuilder.createQuery(CategoryWrapper.class);   
    Root<Invoice> invoiceRoot = criteria.from(Invoice.class);
    Join<Invoice, Category> invoiceJoin = invoiceRoot.join(Invoice_.category);

    criteria.select(
                criteriaBuilder.construct(
                        CategoryWrapper.class,
                        invoiceJoin.get(Category_.id),
                        invoiceJoin.get(Category_.name),
                        criteriaBuilder.count(invoiceRoot.get(Invoice_.id))
            )
        );
    criteria.groupBy(invoiceJoin.get(Category_.id));
    return session.createQuery(criteria).getResultList();

我的问题是:即使没有特定类别的发票,如何获得使用次数的所有类别?

实体

@Entity
@Table(name = "categories")
public class Category {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;

@Column(name = "name")
private String name;

[... getter and setter ]

}


@Entity
@Table(name = "invoice")

public class Invoice {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;

@Column(name = "date")
private Date date;

@ManyToOne
@JoinColumn(name = "category_id")
private Category category;

@Column(name = "description")
private String description;

@Column(name = "amount")
private String amount;

@Column(name = "income", columnDefinition = "BOOLEAN")
private boolean income;

[...getter and setter...]   

}

EDIT1

更新了SQL以使用左连接。但是,在Java代码中使用LEFT连接不起作用。

Join<Invoice, Category> invoiceJoin = invoiceRoot.join(Invoice_.category, JoinType.LEFT);

我只获得带有发票的类别(如上图所示)。但是在数据库中,可以使用更多类别:

categories in database

EDIT2

由于发票是左表,类别是右表,因此我尝试使用RIGHT连接

Join<Invoice, Category> invoiceJoin = invoiceRoot.join(Invoice_.category, JoinType.RIGHT);

但这没用

  

由以下原因引起:java.lang.UnsupportedOperationException:右联接不是   支持

EDIT3

我检查了控制台输出:即使我使用JoinType.LEFT(如EDIT1中所示),程序仍将使用INNER联接

select category1_.id as col_0_0_, category1_.name as col_1_0_, count(invoice0_.id) as col_2_0_ from invoice invoice0_ inner join categories category1_ on invoice0_.category_id=category1_.id group by category1_.id

但是为什么?

0 个答案:

没有答案