2008-09-11 17 views
7

Estoy buscando un constructor para HQL en Java. Quiero para deshacerse de cosas como:Buscando un constructor HQL (Hibernate Query Language)

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

prefiero tener algo como:

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

Googled un poco, y no pude encontrar uno.

Escribí & que se ajusta a mis necesidades por ahora, pero me gustaría encontrar uno que tenga más usuarios y pruebas que yo solo.

Nota: Me gustaría ser capaz de hacer cosas como esta y más, lo que no pude ver con la API Criterios:

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

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

Gracias!

Respuesta

4

@Sébastien Rocca-Serra
Ahora estamos llegando a alguna parte concreta. El tipo de unión que estás tratando de hacer no es realmente posible a través de la API de Criteria, pero una sub consulta debería lograr lo mismo. Primero crea un DetachedCriteria para la tabla de bonificación, luego use el operador IN 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 tablas diferentes en someValue y sus identificaciones no son únicos en todas las mesas. Pero su consulta sufriría el mismo defecto.

+0

Gracias, es lo que necesitaba. Agregué una proyección en el campo de identificación en el primer criterio: bonuses.setProjection (Property.forName ("id")); ¿Se requiere/buena práctica/mala práctica? Por qué ? Gracias de nuevo. –

6

¿No lo hace el Criteria API por usted? Se ve casi exactamente como lo que estás pidiendo.

+0

Bingo. Funciona muy bien para mí. –

4

Parece que desea utilizar la API de consulta Criteria 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 usted no tiene acceso a la sesión de Hibernate, puedes utilizado 'DetachedCriteria', así:

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

Si quería para obtener toda la que tiene un bono con un ID específico que podría hacer lo siguiente:

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

para más infromation echa un vistazo a Criteria Queries de la documentación de Hibernate

2

@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. Hibernate lo hace automáticamente, si y solo si tiene la asignación entre Stock y Bonus configuración y si bonus es una propiedad de Stock. Criteria.list() devolverá Stock objetos y solo debe llamar al stock.getBonus().

Nota, si quieres hacer algo como

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

Necesita utilizar Criteria.createAlias(). Sería algo así como

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

Gracias por las respuestas, me estoy acercando! Pero estoy tratando de seleccionar todas las acciones cuya propiedad someValue apunta a cualquier bonificación de la mesa de bonificación ... –

2

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

¿Por qué no usa NAMED QUERIES? El aspecto mucho más limpio:

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

me escribió una solución GPL para OMERO que se podría construir fácilmente se adapte a su 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 estados "Seleccionar-> de-> join-> where-> fin ", etc. y se mantiene al día con los parámetros opcionales. Hubo varias consultas que la API de Criteria no pudo realizar (ver HHH-879), así que al final fue más simple escribir esta pequeña clase para envolver StringBuilder. (Nota: no es un billete HHH-2407 describir una rama de hibernación que debe unificar los dos Después de eso, es probable que tenga sentido para volver a visitar la API Criteria.)

+0

Interesante, gracias! –

2

Tome un vistazo al paquete de búsqueda disponibles en el proyecto hibernate-generic-dao . Esta es una implementación bastante decente de HQL Builder.

2

Sé que este hilo es bastante viejo, pero yo también estaba buscando un HqlBuilder Y me encontré con este "screensaver" project
no es un protector de pantalla de Windows, que es un "Sistema Laboratorio de Información de Gestión (LIMS) de alto rendimiento instalaciones de detección (HTS) que realizan pantallas de moléculas pequeñas y RNAi. "

Contiene un HQLBuilder que se ve bastante bien.
Aquí está una lista de ejemplos de 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(); 
... 
+0

Interesante, gracias! –

6

Para un enfoque de tipo seguro a su problema, considere Querydsl.

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 apoya JPA/Hibernate, JDO, SQL y colecciones de Java.

Soy el mantenedor de Querydsl, por lo que esta respuesta es parcial.

+0

¡Gracias, echaré un vistazo! –

5

Para otra consulta de tipo seguro dsl, recomiendo http://www.torpedoquery.org.La biblioteca todavía es joven, pero proporciona seguridad de tipo mediante el uso directo de las clases de su entidad. Esto significa errores tempranos del compilador cuando la consulta ya no se aplica antes de refactorizar o rediseñar.

También les di un ejemplo. Creo que a partir de las publicaciones que cuando tratan de hacer una restricción subconsulta, por lo basé el exemple en que:

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

Ahora también están disponibles los JPA Type Safe consulta estándar y un menor estándar, pero también es bueno Object Query

Ejemplos:

APP SEGURO tipo

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

Query Objects

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