Создание Hibernat Query с CriteriaBuilder, включая Join, Group By и Count в Java - PullRequest
0 голосов
/ 28 июня 2019

В моей Java-программе я получил две сущности Invoice и Category (например, страховка, зарплата, машина, ...).Каждый 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, я изучалофициальная документация, но документация показывает только примеры, основанные на отношениях Персона и Адрес.Однако в моем случае Категория не имеет прямой ссылки на Счет-фактуру (все наоборот: каждый счет имеет идентификатор категории).Поэтому я поиграл с кодом и придумал следующий исходный код.Который, очевидно, имеет один серьезный недостаток, так как я не получаю категории без счетов:

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

Я получаю только категории с инвойсами (как показано на рисунке выше).Но в базе данных доступно больше категорий:

categories in database

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

Но почему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...