Выберите количество вхождений каждого статуса в другой таблице, используя критерии jpa

Вы можете достичь этого несколькими способами.

let foo = {
    bar: 'Hello World'
};

foo.bar;
foo['bar'];

Обозначение скобок особенно мощно, так как оно позволяет вам получить доступ к свойству на основе переменной:

let foo = {
    bar: 'Hello World'
};

let prop = 'bar';

foo[prop];

Это может быть расширено до циклизации по каждому свойству объекта. Это может казаться излишним из-за новых конструкций JavaScript, таких как ... из ..., но помогает иллюстрировать прецедент:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

for (let prop in foo.getOwnPropertyNames()) {
    console.log(foo[prop]);
}

Оба точечных и скобковых обозначения также работают как ожидалось для вложенных объектов :

let foo = {
    bar: {
        baz: 'Hello World'
    }
};

foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;

Деструктурирование объекта

Мы могли бы также рассмотреть разрушение объекта как средство доступа к свойству в объекте, но следующим образом:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

let prop = 'last';
let { bar, baz, [prop]: customName } = foo;

// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
1
задан berty 24 March 2019 в 09:56
поделиться

1 ответ

Ваш запрос может быть переписан без объединения подзапросов:

SELECT
    a.id_cm,
    a.type
    COUNT(CASE WHEN b.status = 'PENDING' THEN 1 ELSE NULL END) countPending,
    COUNT(CASE WHEN b.status = 'FAILED' THEN 1 ELSE NULL END) countFailed,
    COUNT( CASE WHEN b.status = 'PROCESSED' THEN 1 ELSE NULL END ) countProcessed
FROM CM AS a
LEFT JOIN CM_PARAM AS b ON a.id_cm = b.id_cm
WHERE a.id_cm = ?1
GROUP BY a.id_cm, a.type

Вам нужно будет добавить обратную сторону ассоциации к Cm:

@OneToMany(mappedBy = "cm")
private Set<CmParam> params;

(в противном случае, вам потребуется RIGHT JOIN от CmParam до Cm, что-то, что Hibernate не поддерживает)

Запрос Criteria становится следующим:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<? extends Object[]> cq = cb.createQuery(new Object[0].getClass());

Root<Cm> a = cq.from(Cm.class);
Join<Cm, CmParam> b = a.join("params", JoinType.LEFT);
cq.where(cb.equal(a.get("idCm"), cb.parameter(Long.class, "idCm")));
cq.groupBy(a.get("idCm"), a.get("type"));
cq.multiselect(
        a.get("idCm"),
        a.get("type"),
        cb.count(cb.selectCase()
                .when(cb.equal(b.get("status"), "PENDING"), 1L)
                .otherwise(cb.nullLiteral(Long.class))),
        cb.count(cb.selectCase()
                .when(cb.equal(b.get("status"), "FAILED"), 1L)
                .otherwise(cb.nullLiteral(Long.class))),
        cb.count(cb.selectCase()
                .when(cb.equal(b.get("status"), "PROCESSED"), 1L)
                .otherwise(cb.nullLiteral(Long.class))));

Обратите внимание, что результат имеет тип Object[]. Если вы хотите использовать свой текущий подход с переходными полями, самый простой способ - добавить соответствующий конструктор в Cm и использовать метод cb.construct():

cq.select(cb.construct(Cm.class, a.get("idCm"), a.get("type"), ...))

Обратите внимание:

[ 1128]
  • , если вы не хотите добавлять поле params в Cm, но у вас все в порядке с INNER JOIN, вы можете просто использовать вместо них Root<CmParam> b = cq.from(CmParam.class) и Join<CmParam, Cm> a = b.join("cm").
  • если в своем фактическом запросе вы выбираете больше атрибутов из Cm, чем просто cmId и status, вам, вероятно, потребуется перечислить их все также в groupBy
  • [1128 ]
    0
    ответ дан crizzis 24 March 2019 в 09:56
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: