Question

je recherche un constructeur pour HQL en Java.Je veux me débarrasser de choses comme :

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

Je préférerais avoir quelque chose comme :

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

J'ai cherché un peu sur Google et je n'en ai pas trouvé.

J'ai écrit un message rapide et stupide HqlBuilder cela répond à mes besoins pour le moment, mais j'aimerais en trouver un qui ait plus d'utilisateurs et de tests que moi seul.

Note:J'aimerais pouvoir faire des choses comme celle-ci et bien plus encore, ce que je n'ai pas réussi à faire avec l'API Criteria :

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

c'est à dire.sélectionner toutes les actions dont la propriété someValue pointe vers n'importe lequel bonus du tableau Bonus.

Merci!

Était-ce utile?

La solution

@Sébastien Rocca-Serra
Maintenant, nous arrivons à quelque chose de concret.Le type de jointure que vous essayez d'effectuer n'est pas vraiment possible via l'API Criteria, mais une sous-requête devrait accomplir la même chose.Vous créez d'abord un DetachedCriteria pour la table bonus, puis utilisez le IN opérateur pour someValue.

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

Ceci équivaut à

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

Le seul inconvénient serait que vous ayez des références à différentes tables dans someValue et vos identifiants ne sont pas uniques sur toutes les tables.Mais votre requête souffrirait du même défaut.

Autres conseils

Est-ce que le API de critères Fais le pour toi?Cela ressemble presque exactement à ce que vous demandez.

Pour une approche sécurisée de votre problème, considérez Requêtedsl.

L'exemple de requête devient

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

Querydsl utilise APT pour la génération de code comme JPA2 et prend en charge les collections JPA/Hibernate, JDO, SQL et Java.

Je suis le responsable de Querydsl, cette réponse est donc biaisée.

Pour une autre requête DSL de type sécurisé, je recommande http://www.torpedoquery.org.La bibliothèque est encore jeune mais elle assure la sécurité des types en utilisant directement les classes de votre entité.Cela signifie des erreurs précoces du compilateur lorsque la requête ne s'applique plus avant la refactorisation ou la refonte.

Je vous ai également fourni un exemple.Je pense, d'après vos messages, que vous essayiez de faire une restriction de sous-requête, j'ai donc basé l'exemple sur cela :

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

Il semble que vous souhaitiez utiliser l'API de requête Criteria intégrée à Hibernate.Pour faire votre requête ci-dessus, cela ressemblerait à ceci :

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

Si vous n'avez pas encore accès à la session Hibernate, vous pouvez utiliser 'DetachedCriteria' comme ceci :

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

Si vous souhaitez obtenir tous les titres dotés d'un bonus avec un identifiant spécifique, vous pouvez procéder comme suit :

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

Pour plus d'informations, consultez Requêtes de critères à partir de la documentation Hibernate

@Sébastien Rocca-Serra

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

C'est juste une jointure.Hibernate le fait automatiquement, si et seulement si vous disposez du mappage entre Stock et Bonus configuration et si bonus est une propriété de Stock. Criteria.list() reviendra Stock objets et vous appelez simplement stock.getBonus().

Notez que si vous voulez faire quelque chose comme

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

Vous devez utiliser Criteria.createAlias().Ce serait quelque chose comme

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

L'API Criteria ne fournit pas toutes les fonctionnalités disponibles dans HQL.Par exemple, vous ne pouvez pas effectuer plusieurs jointures sur la même colonne.

Pourquoi n'utilises-tu pas REQUÊTES NOMMÉES?Le look beaucoup plus épuré :

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

J'ai écrit une solution GPL pour OMERO que vous pouvez facilement créer en fonction de votre situation.

Usage:

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

Il fonctionne comme une machine à états "select->from->join->where->order", etc.et suit les paramètres facultatifs.Il y avait plusieurs requêtes que l'API Criteria ne pouvait pas exécuter (voir HHH-879), donc au final, il était plus simple d'écrire cette petite classe pour envelopper StringBuilder.(Note:il y a un billet HHH-2407 décrivant une branche Hibernate qui devrait unifier les deux.Après cela, il serait probablement judicieux de revoir l'API Criteria.)

Jetez un œil au package de recherche disponible sur le mise en veille prolongée-générique-dao projet.Il s'agit d'une implémentation assez décente de HQL Builder.

Je sais que ce fil est assez ancien, mais je cherchais aussi un HqlBuilder et j'ai trouvé ça projet "économiseur d'écran"
Ce n'est pas un économiseur d'écran Windows, c'est un "Système de gestion des informations de laboratoire (LIMS) pour les installations de criblage à haut débit (HTS) qui effectuent des criblages de petites molécules et d'ARNi."

Il contient un HQLBuilder qui semble plutôt bien.
Voici un exemple de liste des méthodes disponibles :

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

Maintenant sont également disponibles les versions standard Coffre-fort de type JPA requête et un moins standard mais aussi bon Requête d'objet

Exemples:

Coffre-fort de type 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();

Requête d'objet

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top