Как рассчитать разницу по нескольким столбцам - PullRequest
10 голосов
/ 08 февраля 2012

Как я могу, используя API критериев JPA, сделать следующее:

select count(distinct column1, column2) from table

Сделать это на одном столбце / пути просто, используя CriteriaBuilder.countDistinct, но как я могу сделать это на двух путях / столбцах

Ответы [ 3 ]

5 голосов
/ 28 августа 2014

Вот поздний ответ :-), хотя я не уверен, что все изменилось.

Недавно я столкнулся с той же самой потребностью и обошел ее, используя concat, то есть объединяя столбцы в псевдостолбец , затем countDistinct в псевдостолбце.

Но я не смог использовать criteriaBuilder.concat, потому что он генерировал JPQL, используя || для конкатенации, что Hibernate имел проблемы с .

К счастью, есть @Formula, поэтому я сопоставил псевдостолбец с полем с помощью @Formula:

@Entity
public class MyEntity {
  @Column(name="col_a")
  private String colA;

  @Column(name="col_b")
  private String colB;

  @Formula("concat(col_a, col_b)") // <= THE TRICK
  private String concated;
}

Таким образом, я наконец смогу использовать поле concated для CriteriaBuilder.countDistinct:

//...
Expression<?> exp = criteriaBuilder.countDistinct(entity.get("concated"));
criteriaQuery.select(exp);

TypedQuery<Long> query = entityManager.createQuery(criteriaQuery);
return query.getSingleResult();

Я бы хотел, чтобы JPA (или, надеюсь, уже) поддерживал countDistinct с несколькими столбцами, тогда можно было бы избежать всего этого беспорядка.

1 голос
/ 21 июля 2015

Вы можете использовать спящий диалект для этой задачи. Для этого создайте свой собственный диалект, который расширяет используемый диалект БД ( список всех диалектов ), а затем зарегистрируйте новую функцию. Например, я использую MySQL 5 с движком InnoDB:

public final class MyDialect extends MySQL5InnoDBDialect {
    public MyDialect() {
        super();
        registerFunction("pairCountDistinct", new SQLFunctionTemplate(LongType.INSTANCE, "count(distinct ?1, ?2)"));
    }
}

После этого добавьте новое свойство в persistence.xml:

<property name="hibernate.dialect" value="com.example.dialect.MyDialect" />

И теперь вы можете использовать эту функцию:

// some init actions
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
final Root<SomeEntity> root = criteria.from(SomeEntity.class);
criteria.select(builder.function("pairCountDistinct", Long.class, root.get(SomeEntity_.field1), root.get(SomeEntity_.field2)));
final long result = entityManager.createQuery(criteria).getSingleResult();
// some close actions
0 голосов
/ 08 февраля 2012

Похоже, что нет способа сделать это с JPA2

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