QueryDSL: как сделать заказ по NEWID()?

Как я могу написать:

SELECT TOP 1 x
FROM y
ORDER BY NEWID()

используя querydsl-sql?

(См. https://stackoverflow.com/a/4980733/14731 для объяснения того, что делает запрос)


person Gili    schedule 06.04.2015    source источник
comment
Итак, querydsl — это что-то вроде строки Linq для Java?   -  person alas    schedule 06.04.2015
comment
Область @alas querydsl ограничена созданием безопасных для типов операторов SQL. Я никогда не использовал LINQ, но я считаю, что его возможности гораздо шире.   -  person Gili    schedule 06.04.2015
comment
Но, похоже, он не поддерживает определенные проприетарные функции сервера sql, такие как newid(). Итак, в основном вы ищете запрос querydsl-sql для возврата случайной записи из таблицы, верно?   -  person alas    schedule 06.04.2015
comment
@alas Точнее, я ищу способ вызывать пользовательские функции из QueryDSL.   -  person Gili    schedule 06.04.2015
comment
так не будет ли применяться TemplateExpression? см. это: stackoverflow.com/ вопросы/22984343/   -  person alas    schedule 06.04.2015


Ответы (2)


В итоге я сделал следующее:

import com.mysema.query.types.expr.StringExpression;
import com.mysema.query.types.template.StringTemplate;

/**
 * SQL Server specific expressions.
 *
 * @author Gili Tzabari
 */
public final class CustomExpressions {

    private static final StringExpression newId = StringTemplate.create("NEWID()");

    /**
     * Prevent construction.
     */
    private CustomExpressions() {
    }

    /**
     * @return NEWID()
     */
    public static StringExpression newId() {
        return newId;
    }
}

[...]

CustomExpressions expressions = new CustomExpressions();
new SQLQuery(connection, configuration).query().from(y).
  orderBy(expressions.newId().asc()).
  limit(1).uniqueResult(x);
person Gili    schedule 14.04.2015
comment
+1 за использование StringTemplate, это лучшее решение, чем то, что я предложил. Лично я бы предпочел служебный класс для CustomExpressions - final, с частным конструктором и методом public static StringExpression newId(). о чем ты думаешь? - person Robert Bain; 14.04.2015
comment
@RobertBain, я согласен с текущей реализацией этого класса. Для синглтона с изменяемым состоянием я обычно оставляю класс как есть и использую IoC для создания его экземпляра как синглтона. В любом случае, я обновлю ответ. Спасибо за ответ! - person Gili; 14.04.2015
comment
Это выглядит нормально, но пустой конструктор должен быть закрытым. - person Timo Westkämper; 16.04.2015
comment
Если бы я был супер-педантичным, newId должен был быть NEW_ID. - person Robert Bain; 16.04.2015

Это не самое элегантное решение, но вы можете использовать метод addFlag(QueryFlag.Position position, String flag), задокументированный здесь.

E.G.

query.addFlag(QueryFlag.Position.END, "ORDER BY NEWID()");

Я обнаружил, что когда queryDSL отказывается работать хорошо, и под «хорошим поведением» я подразумеваю, когда API не поддерживает то, что я пытаюсь сделать, есть несколько способов, по существу, заставить String в вашем запросе. Это наименее плохой способ, по моему опыту.

person Robert Bain    schedule 14.04.2015