В моей 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, я изучалофициальная документация, но документация показывает только примеры, основанные на отношениях Персона и Адрес.Однако в моем случае Категория не имеет прямой ссылки на Счет-фактуру (все наоборот: каждый счет имеет идентификатор категории).Поэтому я поиграл с кодом и придумал следующий исходный код.Который, очевидно, имеет один серьезный недостаток, так как я не получаю категории без счетов:
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 не работает.
Join<Invoice, Category> invoiceJoin = invoiceRoot.join(Invoice_.category, JoinType.LEFT);
Я получаю только категории с инвойсами (как показано на рисунке выше).Но в базе данных доступно больше категорий:
EDIT2
В качестве накладных есть левая таблица икатегории - это правильная таблица. Я попытался использовать RIGHT join
Join<Invoice, Category> invoiceJoin = invoiceRoot.join(Invoice_.category, JoinType.RIGHT);
, но это не сработало
Причина: java.lang.UnsupportedOperationException: RIGHT JOIN не поддерживается
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
Но почему?