Pregunta

Busco constructor para HQL en Java.Quiero deshacerme de cosas como:

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

Prefiero algo como:

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

Busqué en Google un poco y no pude encontrar ninguno.

Escribí un rápido y tonto. HqlBuilder eso se adapta a mis necesidades por ahora, pero me encantaría encontrar uno que tenga más usuarios y pruebas que yo solo.

Nota:Me gustaría poder hacer cosas como esta y más, que no pude hacer con Criteria API:

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

es decir.seleccione todas las acciones cuya propiedad someValue puntos a cualquier bonificación de la tabla de bonificación.

¡Gracias!

¿Fue útil?

Solución

@Sébastien Rocca-Serra
Ahora estamos llegando a algo concreto.El tipo de unión que está intentando realizar no es realmente posible a través de la API de Criteria, pero una subconsulta debería lograr lo mismo.Primero creas un DetachedCriteria para la tabla de bonificación, luego use el IN operador para someValue.

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

Esto es equivalente a

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

El único inconveniente sería si tiene referencias a diferentes tablas en someValue y sus ID no son únicos en todas las tablas.Pero su consulta sufriría el mismo defecto.

Otros consejos

¿No API de criterios ¿hazlo por ti?Se ve casi exactamente como lo que estás pidiendo.

Para un enfoque seguro para su problema, considere consultadsl.

La consulta de ejemplo se convierte en

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

Querydsl utiliza APT para la generación de código como JPA2 y admite colecciones JPA/Hibernate, JDO, SQL y Java.

Soy el mantenedor de Querydsl, por lo que esta respuesta está sesgada.

Para otra consulta dsl con seguridad de tipos, recomiendo http://www.torpedoquery.org.La biblioteca aún es joven pero proporciona seguridad de tipos al utilizar directamente las clases de su entidad.Esto significa errores tempranos del compilador cuando la consulta ya no se aplica antes de la refactorización o el rediseño.

También te proporcioné un ejemplo.Creo que por tus publicaciones estabas intentando hacer una restricción de subconsulta, así que basé el ejemplo en eso:

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

Parece que desea utilizar la API de consulta de criterios integrada en Hibernate.Para hacer su consulta anterior se vería así:

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

Si aún no tiene acceso a la sesión de Hibernación, puede utilizar 'DetachedCriteria' de esta manera:

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

Si deseas obtener todas las Acciones que tienen un Bono con un ID específico, puedes hacer lo siguiente:

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

Para más información consulte Consultas de criterios de los documentos de Hibernate

@Sébastien Rocca-Serra

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

Eso es sólo una unión.Hibernar lo hace automáticamente, si y sólo si tienes el mapeo entre Stock y Bonus configuración y si bonus es una propiedad de Stock. Criteria.list() regresará Stock objetos y tu solo llamas stock.getBonus().

Tenga en cuenta que si desea hacer algo como

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

Necesitas usar Criteria.createAlias().Seria algo asi

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

Criteria API no proporciona todas las funciones disponibles en HQL.Por ejemplo, no puede realizar más de una combinación en la misma columna.

¿Por qué no usas CONSULTAS CON NOMBRE?El aspecto mucho más limpio:

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

Escribí una solución GPL para OMERO que podrías crear fácilmente y que se adapte a tu situación.

Uso:

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

Funciona como una máquina de estado "seleccionar->desde->unirse->dónde->ordenar", etc.y se mantiene al día con los parámetros opcionales.Hubo varias consultas que la API de Criteria no pudo realizar (consulte HHH-879), por lo que al final fue más sencillo escribir esta pequeña clase para envolver StringBuilder.(Nota:hay un boleto HHH-2407 describiendo una rama de Hibernate que debería unificar las dos.Después de eso, probablemente tendría sentido volver a visitar la API de Criteria)

Eche un vistazo al paquete de búsqueda disponible en hibernar-dao-genérico proyecto.Esta es una implementación de HQL Builder bastante decente.

Sé que este hilo es bastante antiguo, pero también estaba buscando un HqlBuilder y encontré esto proyecto "salvapantallas"
No es un protector de pantalla de Windows, es un "Sistema de gestión de información de laboratorio (LIMS) para instalaciones de detección de alto rendimiento (HTS) que realizan pruebas de ARNi y moléculas pequeñas."

Contiene un HQLBuilder que se ve bastante bien.
Aquí hay una lista de muestra de los métodos 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();
...

Ahora también están disponibles los estándar Caja fuerte tipo JPA consulta y un menos estándar pero también bueno Consulta de objetos

Ejemplos:

Caja fuerte tipo 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();

Consulta de objetos

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);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top