【问题标题】:How to escape reserved words in Hibernate's HQL如何在 Hibernate 的 HQL 中转义保留字
【发布时间】:2011-08-06 21:11:49
【问题描述】:

我使用以下查询来获得一个带有索引idtextobjectjava.util.Map

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

...但object 似乎是保留字。例如obj 是可以的。目前在 HQL 中以 MySQL 使用反引号转义的方式转义 alias 的方法是什么?

使用反引号会出现以下错误:

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

【问题讨论】:

    标签: java hibernate hql


    【解决方案1】:

    在相关主题中,转义列名中的保留字就像在表别名前面一样简单。没有反引号、方括号等。只需替换

    select where from mytable
    

    作者:

    select t.where from mytable t
    

    (注意:我并不是说将“where”作为列名是个好主意 ;-)

    【讨论】:

      【解决方案2】:

      您可以通过使用自定义“别名映射”转换器的解决方法来实现它,因此您的代码将更改为类似的内容

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

      然后使用这个类:

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

      【讨论】:

      • 谢谢,这是迄今为止最好的解决方案。
      • 这仅适用于以非常特定的方式选择的名称。如果您想解决写在“where”子句或其他地方的关键字怎么办?
      【解决方案3】:

      back tics 概念在休眠中有效。不幸的是,这仅在您完成注释配置后才有效...

      您可以尝试以不同的方式执行此操作(无需注释)。

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

      这里你需要创建一个使用中的构造函数,它接受一个 id、name、object 元素 & 的顺序。

      【讨论】:

      • Backtics 也可以在 XML 映射文件中使用。但我想逃避 HQL 中的事情。别名的要点是可以任意分配它们。我使用Map 作为系统解耦部分之间的最小公分母。如果他们能工作,那真的很方便。
      【解决方案4】:

      反引号对别名不起作用吗? Hibernate documentation 表示将它们用于字段。

      其他问题:

      • 是否可以使用其他值?
      • 为什么是地图(它也包含原始值)而不是列表? 可以从原始 Object 中检索 Id 和 Name。

      【讨论】:

      • 我试过ofc。它们似乎在查询中不起作用。我想使用地图,因为它非常灵活,并且数据被提供给其他 API。
      猜你喜欢
      • 1970-01-01
      • 2010-11-12
      • 2011-03-22
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多