简体   繁体   中英

How to escape reserved words in Hibernate's HQL

I use the following query to get a java.util.Map with indexes id , text and object :

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

... but object seems to be a reserved word. For example obj is OK. What is the current way to escape an alias in HQL the way MySQL uses backtick escapes?

Using backtick gives the following 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]

You could achieve it by a workaround using your custom "alias to map" transformer, so your code would change to something like this

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

And then using this class:

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

On a related topic, escaping a reserved word in a column name is as easy as prepending with a table alias. No backticks, square brackets, etc. Simply replace

select where from mytable

by:

select t.where from mytable t

(note: i'm NOT saying it's a good idea to have "where" as column name ;-)

the back tics concept works in hibernate.. unfortunately this only works if you've done annotation config...

you can try to do this in a different way (without annotations).

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

here you need to create a constructor in use which accepts an id, name, object elements & in that order.

Do backticks not work on aliases? The Hibernate documentation says to use them for fields.

Other questions:

  • Is another value possible?
  • Why a map (it also contains the original value) and not a List? Id and Name could be retrieved from the original Object.

Ok, i'm really late on this question but since the above solutions didn't work for me i thought i'd post the solution that did.

Our issue was a field named "row". The solution depending on xml or annotation would be:

@Column(name="`row`")
private String row;
<property name="row" column="`row`" access="field" not-null="true"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM