Вопрос

Я ищу строителя для HQL на языке Java.Я хочу избавиться от таких вещей, как:

StringBuilder builder = new StringBuilder()
    .append("select stock from ")
    .append( Stock.class.getName() )
    .append( " as stock where stock.id = ")
    .append( id );

Я бы предпочел что-то вроде:

HqlBuilder builder = new HqlBuilder()
    .select( "stock" )
    .from( Stock.class.getName() ).as( "stock" )
    .where( "stock.id" ).equals( id );

Я немного погуглил, но ничего не смог найти.

Я написал быстрый и тупой HqlBuilder на данный момент это соответствует моим потребностям, но я бы хотел найти тот, у которого больше пользователей и тестов, чем у меня одного.

Примечание:Я бы хотел иметь возможность делать подобные вещи и многое другое, чего мне не удалось сделать с помощью Criteria API:

select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.someValue = bonus.id

т.е.выберите все акции, собственность которых someValue указывает на Любой бонус из бонусной таблицы.

Спасибо!

Это было полезно?

Решение

@Sébastien Rocca-Serra
Теперь мы приближаемся к чему-то конкретному.Соединение, которое вы пытаетесь выполнить, на самом деле невозможно с помощью Criteria API, но вложенный запрос должен выполнить то же самое.Сначала вы создаете DetachedCriteria для получения бонусной таблицы используйте IN оператор для someValue.

DetachedCriteria bonuses = DetachedCriteria.forClass(Bonus.class);
List stocks = session.createCriteria(Stock.class)
    .add(Property.forName("someValue").in(bonuses)).list();

Это эквивалентно

select stock
from com.something.Stock as stock
where stock.someValue in (select bonus.id from com.something.Bonus as bonus)

Единственным недостатком было бы, если бы у вас были ссылки на разные таблицы в someValue и ваши идентификаторы не уникальны для всех таблиц.Но ваш запрос будет страдать от того же недостатка.

Другие советы

Не делает ли API критериев сделать это для тебя?Это выглядит почти в точности так, как вы просите.

Для типобезопасного подхода к вашей проблеме рассмотрим Querydsl Запрос.

Пример запроса становится

HQLQuery query = new HibernateQuery(session);
List<Stock> s = query.from(stock, bonus)
  .where(stock.someValue.eq(bonus.id))
  .list(stock);

Querydsl использует APT для генерации кода, подобного JPA2, и поддерживает коллекции JPA / Hibernate, JDO, SQL и Java.

Я являюсь сопровождающим Querydsl, поэтому этот ответ предвзят.

Для другого типобезопасного запроса dsl я рекомендую http://www.torpedoquery.org.Библиотека все еще молода, но она обеспечивает безопасность типов за счет прямого использования классов вашей сущности.Это означает ранние ошибки компилятора, когда запрос больше не применяется до проведения рефакторинга или редизайна.

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

import static org.torpedoquery.jpa.Torpedo.*;

Bonus bonus = from(Bonus.class);
Query subQuery = select(bonus.getId());

Stock stock = from(Stock.class);
where(stock.getSomeValue()).in(subQuery);

List<Stock> stocks = select(stock).list(entityManager);

Похоже, вы хотите использовать API запроса критериев, встроенный в Hibernate.Чтобы выполнить ваш приведенный выше запрос, это выглядело бы примерно так:

List<Stock> stocks = session.createCriteria(Stock.class)
    .add(Property.forName("id").eq(id))
    .list();

Если у вас еще нет доступа к сеансу гибернации, вы можете использовать 'DetachedCriteria' следующим образом:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class) 
    .add(Property.forName("id").eq(id));

Если вы хотите получить все акции, которые имеют Бонус с определенным идентификатором, вы могли бы сделать следующее:

DetachedCriteria criteria = DetachedCriteria.forClass(Stock.class)
     .createCriteria("Stock")
          .add(Property.forName("id").eq(id)));

Для получения дополнительной информации ознакомьтесь с Запросы по критериям из документации по гибернации

@Sébastien Rocca-Serra

select stock
from com.something.Stock as stock, com.something.Bonus as bonus
where stock.bonus.id = bonus.id

Это всего лишь объединение.Hibernate делает это автоматически, тогда и только тогда, когда у вас есть сопоставление между Stock и Bonus настройка и если bonus является свойством Stock. Criteria.list() вернется Stock объекты, и вы просто вызываете stock.getBonus().

Обратите внимание, если вы хотите сделать что-то вроде

select stock
from com.something.Stock as stock
where stock.bonus.value > 1000000

Вам нужно использовать Criteria.createAlias().Это было бы что-то вроде

session.createCriteria(Stock.class).createAlias("bonus", "b")
   .add(Restrictions.gt("b.value", 1000000)).list()

Criterions API не предоставляет всех функциональных возможностей, доступных в HQL.Например, вы не можете выполнить более одного объединения над одним и тем же столбцом.

Почему бы вам не использовать ИМЕНОВАННЫЕ ЗАПРОСЫ?Внешний вид намного более чистый:

Person person = session.getNamedQuery("Person.findByName")
                             .setString(0, "Marcio")
                             .list();

Я написал решение GPL для OMERO, которое вы могли бы легко создать в соответствии с вашей ситуацией.

Использование:

QueryBuilder qb = new QueryBuilder();
qb.select("img");
qb.from("Image", "img");
qb.join("img.pixels", "pix", true, false);

// Can't join anymore after this
qb.where(); // First
qb.append("(");
qb.and("pt.details.creationTime > :time");
qb.param("time", new Date());
qb.append(")");
qb.and("img.id in (:ids)");
qb.paramList("ids", new HashSet());
qb.order("img.id", true);
qb.order("this.details.creationEvent.time", false);

Он функционирует как конечный автомат "выбрать-> из-> присоединиться-> где-> заказать" и т.д.и поддерживает необязательные параметры.Было несколько запросов, которые Criteria API не смог выполнить (см. ХХХХ-879), так что в конце концов было проще написать этот небольшой класс для переноса StringBuilder.(Примечание:есть билет HHH-2407 описание ветви гибернации, которая должна объединить их.После этого, вероятно, имело бы смысл повторно посетить Criteria API)

Взгляните на пакет поиска, доступный на сайте переход в спящий режим-универсальный-dao проект.Это довольно приличная реализация HQL Builder.

Я знаю, что эта тема довольно старая, но я также искал HqlBuilder И нашел это Проект "скринсейвер"
Это НЕ заставка Windows, это "Система управления лабораторной информацией (LIMS) для высокопроизводительных скрининговых установок (HTS), которые проводят скрининг на основе малых молекул и RNAi."

Он содержит HQLBuilder, который выглядит довольно хорошо.
Вот примерный список доступных методов:

...
HqlBuilder select(String alias);
HqlBuilder select(String alias, String property);
HqlBuilder from(Class<?> entityClass, String alias);
HqlBuilder fromFetch(String joinAlias, String joinRelationship, String alias);
HqlBuilder where(String alias, String property, Operator operator, Object value);
HqlBuilder where(String alias, Operator operator, Object value);
HqlBuilder where(String alias1, Operator operator, String alias2);
HqlBuilder whereIn(String alias, String property, Set<?> values);
HqlBuilder whereIn(String alias, Set<?> values);
HqlBuilder where(Clause clause);
HqlBuilder orderBy(String alias, String property);
HqlBuilder orderBy(String alias, SortDirection sortDirection);
HqlBuilder orderBy(String alias, String property, SortDirection sortDirection);
String toHql();
...

Теперь также доступны стандартные Сейф типа JPA запрос и менее стандартный, но тоже хороший Запрос объекта

Примеры:

Сейф типа JPA

EntityManager em = ...
CriteriaBuilder qb = em.getCriteriaBuilder();
CriteriaQuery<Stock> c = qb.createQuery(Stock.class);
Root<Stock> = c.from(Stock.class);
Predicate condition = qb.eq(p.get(Stock_.id), id);
c.where(condition);
TypedQuery<Stock> q = em.createQuery(c); 
List<Stock> result = q.getResultList();

Запрос объекта

EntityManager em = ...
ObjectQuery<Stock> query = new GenericObjectQuery<Stock>(Stock.class);
Stock toSearch = query.target();
query.eq(toSearch.getId(),id);
List<Stock> res = (List<Stock>)JPAObjectQuery.execute(query, em);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top