2011-04-16 29 views
14

utilizo la siguiente consulta para obtener una java.util.Map con índices id, text y object:cómo escapar de palabras reservadas en HQL de Hibernate

Query q = mySession.createQuery(
    "SELECT u.id AS id, u.name AS text, u AS object FROM User u") 
    .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); 

... pero object parece ser una palabra reservada. Por ejemplo, obj está bien. ¿Cuál es la forma actual de escapar de un alias en HQL de la misma forma que MySQL usa escapes?

El uso de comillas invertidas da el siguiente error:

Exception in thread "main" org.hibernate.QueryException: unexpected char: 
'`' [SELECT u.id AS id, u.name AS text, u AS `object` FROM User u] 

Respuesta

10

Se podía lograrlo por una solución alternativa la utilización de su encargo "alias para mapear" transformador, por lo que su código podría cambiar a algo como esto

Query q = mySession.createQuery(
    "SELECT u.id AS id, u.name AS text, u AS obj FROM User u") 
    .setResultTransformer(
     AliasToMapTransformer.renameAlias("obj", "object").build() 
    ); 

Y a continuación, el uso de esta clase:

public class AliasToMapTransformer extends BasicTransformerAdapter { 

    private Map<String, String> renameAliasMap; 


    public AliasToMapTransformer(Map<String, String> renameAliasMap) { 
     this.renameAliasMap = (renameAliasMap == null) ? Collections.<String, String>emptyMap() : renameAliasMap; 
    } 


    @Override 
    public Object transformTuple(Object[] tuple, String[] aliases) { 
     Map<String, Object> result = new HashMap<String, Object>(tuple.length); 
     for (int i = 0; i < tuple.length; i++) { 
      String alias = aliases[i]; 
      if (alias != null) { 
       String newAlias = renameAliasMap.get(alias); 

       result.put((newAlias != null) ? newAlias : alias, tuple[i]); 
      } 
     } 
     return result; 
    } 


    public static Builder renameAlias(String alias, String newAlias) { 
     return new Builder().renameAlias(alias, newAlias); 
    } 


    public static class Builder { 

     private Map<String, String> aliasConversionMap = new HashMap<String, String>(); 


     public Builder renameAlias(String alias, String newAlias) { 
      aliasConversionMap.put(alias, newAlias); 
      return this; 
     } 


     public AliasToMapTransformer build() { 
      return new AliasToMapTransformer(aliasConversionMap); 
     } 
    } 
} 
+0

Gracias es la mejor solución hasta ahora. – vbence

+0

Esto solo funciona para trabajar alrededor de nombres seleccionados de una manera muy específica. ¿Qué sucede si desea trabajar con palabras clave escritas en una cláusula "where" u otra parte? –

0

No acentos abiertos no funciona en los alias? El Hibernate documentation dice que los use para los campos.

Otras preguntas:

  • es otro valor posible?
  • ¿Por qué un mapa (también contiene el valor original) y no una lista? Identificación y Nombre podrían ser recuperados del Objeto original.
+0

intenté con la función. Ellos medio no funcionan en las consultas. Quiero usar el mapa ya que es bastante compatible y los datos se envían a otra API. – vbence

2

el concepto tics espalda trabaja en hibernación .. lamentablemente esto sólo funciona si usted ha hecho de configuración de anotación ...

se puede tratar de hacer esto de una manera diferente (sin anotaciones).

Query q = session.createQuery("select new User (u.id, u.name, u.object) from User u").list(); 

Aquí es necesario para crear un constructor en uso, que acepta un id, nombre, elementos de objeto & en ese orden.

+0

Backtics se puede utilizar también en el archivo de mapeo XML. Pero quiero escapar de las cosas en HQL. El punto principal de los alias sería que pueden asignarse arbitrariamente. Estoy usando 'Map' como el mínimo común denominador entre las partes desacopladas del sistema. Sería realmente útil si solo funcionaran. – vbence

5

En un tema relacionado, escaparse de una palabra reservada en un nombre de columna es tan fácil como anteponer un alias de tabla. No hay acentos abiertos, corchetes, etc. Sólo tiene que sustituir

select where from mytable 

por:

select t.where from mytable t 

(nota: no estoy diciendo que es una buena idea tener "donde" como nombre de la columna ;-)

Cuestiones relacionadas