WedX - журнал о программировании и компьютерных науках

Спящий режим - группировать по столбцу, собирать в список и ограничивать

В моем приложении у меня есть таблица customer_facts, представленная объектом гибернации:

@Entity
data class PersistedCustomerFacts(
    @Id
    val id: Long,
    val customerId: String
    val factValue: String
)

Он хранит все факты о клиентах. У каждого клиента может быть несколько фактов. Я хочу запросить таблицу и получить результат, состоящий из списка каждого идентификатора клиента с его фактами. Но я также хочу, чтобы он был доступен для просмотра по идентификатору клиента, поэтому, например, я могу получить только первых двух клиентов. Я хотел бы показать пример. Скажем, я хочу получить первые два результата, упорядоченные по идентификатору клиента.

Данные в базе:

id, customerId, factValue
1, 'customerA', 'likes cats'
2, 'customerA', 'likes dogs'
3, 'customerA', 'doesnt likes rats'
4, 'customerB', 'likes cats'
5, 'customerB', 'likes rats'
6, 'customerB', 'likes bikes'
7, 'customerB', 'doesnt likes cats'
8, 'customerC', 'doesnt likes bikes'

окончательный результат будет

[
    {
        "customerId": "customerA",
        "facts": ["likes cats", "likes dogs", "doesnt likes rats"]
    },
    {
        "customerId": "customerB",
        "facts": ["likes cats", "likes rats", "likes bats"]
    },
]

Я надеюсь, что теперь ясно, что у меня есть проблема, особенно с тем, как сделать результат доступным для страниц по полю customerId. Я пробовал что-то вроде этого:

        val criteriaBuilder = entityManager.criteriaBuilder
        val criteriaQuery = criteriaBuilder.createQuery(PersistedCustomerFacts::class.java)
        val customerFacts = criteriaQuery.from(PersistedCustomerFacts::class.java)
        criteriaQuery
            .select(customerFacts)
            .orderBy(criteriaBuilder.asc(customerFacts.get("customerId")));
        val typedQuery = entityManager.createQuery(criteriaQuery)
        typedQuery.firstResult = 0
        typedQuery.maxResults = 2
        return typedQuery.resultList

Однако это плохо, потому что я ограничиваю строки, поэтому я могу не получить все факты некоторого идентификатора клиента. Как решить такую ​​проблему? Может быть, я должен сделать два запроса?

05.05.2020

Ответы:


1

Это идеальный пример использования API расширенного разбиения на страницы предоставляется библиотекой Blaze-Persistence, работающей поверх JPA!

Есть несколько способов сделать это, но для простоты я предполагаю, что у вас есть обратная ассоциация @OneToMany @JoinColumn(name = "customerId") Set<PersistedCustomerFacts> facts, отображаемая в вашей сущности Customer.

С помощью API разбивки на страницы вы можете написать запрос, подобный следующему

CriteriaBuilder<Customer> cb = criteriaBuilderFactory.create(entityManager, Customer.class);
cb.fetch("facts");
PaginatedCriteriaBuilder<Customer> pcb = cb.page(0, 2);
return pcb.getResultList();

Если у вас нет этой обратной ассоциации, вы можете использовать функцию агрегации строк

CriteriaBuilder<Tuple> cb = criteriaBuilderFactory.create(entityManager, Tuple.class);
cb.from(PersistedCustomerFacts.class, "fact");
cb.select("fact.customerId");
cb.select("GROUP_CONCAT(fact.factValue, 'SEPARATOR', ';')");
cb.groupBy("fact.customerId");
PaginatedCriteriaBuilder<Tuple> pcb = cb.page(0, 2);
return pcb.getResultList();

а затем разбить строку на коллекцию.

Если у вас есть логика, написанная с помощью JPA Criteria API, которую вы хотите использовать повторно, вы можете использовать модуль jpa-criteria, который является реализацией JPA Criteria API и генерирует Blaze-Persistence CriteriaBuilder.

07.05.2020
Новые материалы

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

ИИ в аэрокосмической отрасли
Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


Для любых предложений по сайту: [email protected]