Buscando un constructor HQL (Hibernate Query Language)
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!
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
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.
- Fuente: QueryBuilder.java
- Prueba: QueryBuilderPrueba simulada
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);