在Java程序中,我有两个实体Invoice
和Category
(例如保险,薪水,汽车等)。每个Invoice
恰好属于一个Category
。现在,我想显示一个表,其中列出了所有现有类别以及实际用于发票的次数。像这样:
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);
我只获得带有发票的类别(如上图所示)。但是在数据库中,可以使用更多类别:
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
但是为什么?