Как получить полностью материализованный запрос из querydsl

Я пытаюсь использовать querydsl для создания динамических запросов для динамических схем. Я пытаюсь получить только запрос вместо того, чтобы фактически выполнить его.

До сих пор я столкнулся с двумя проблемами: - Обозначение schema.table отсутствует. Вместо этого я получаю только имя таблицы. - Мне удалось получить запрос, но он отделяет переменные и помещает '?' вместо этого это понятно. Но мне интересно, есть ли способ получить полностью материализованный запрос, включая параметры.

Вот моя текущая попытка и результат (я использую MySQLTemplates для создания конфигурации):

private SQLTemplates templates = new MySQLTemplates();
private Configuration configuration = new Configuration(templates); 

String table = "sometable"
Path<Object> userPath = new PathImpl<Object>(Object.class, table);
StringPath usernamePath = Expressions.stringPath(userPath, "username");
NumberPath<Long> idPath = Expressions.numberPath(Long.class, userPath, "id");
SQLQuery sqlQuery = new SQLQuery(connection, configuration)
  .from(userPath).where(idPath.eq(1l)).limit(10);
String query = sqlQuery.getSQL(usernamePath).getSQL();
return query;

И я получаю:

select sometable.username
from sometable
where sometable.id = ?
limit ?

То, что я хотел получить, было:

select sometable.username
from someschema.sometable
where sometable.id = ?
limit ?

Обновление: я придумал этот вид взлома, чтобы получить параметры, материализованные (не идеально и было бы лучше для лучшего решения). Но все же не смог получить нотацию Schema.Table.:

Взлом следует. Пожалуйста, предложите более чистый способ QueryDsl:

String query = cleanQuery(sqlQuery.getSQL(usernamePath));

private String cleanQuery(SQLBindings bindings){
    String query = bindings.getSQL();
    for (Object binding : bindings.getBindings()) {
        query = query.replaceFirst("\\?", binding.toString());
    }
    return query;
}

Ответ 1

Чтобы включить печать схемы, используйте следующий шаблон

SQLTemplates templates = MySQLTemplates.builder()
    .printSchema()
    .build();

Ранее использовались подклассы SQLTemplates, но с тех пор шаблон компоновщика является официальным способом настройки шаблонов http://www.querydsl.com/static/querydsl/3.3.1/reference/html/ch02s03.html#d0e904

И чтобы включить прямую сериализацию литералов, используйте

//configuration level
configuration.setUseLiterals(true);

//query level
configuration.setUseLiterals(true);

Вот полный пример

// configuration
SQLTemplates templates = MySQLTemplates.builder()
    .printSchema()
    .build();
Configuration configuration = new Configuration(templates);

// querying
SQLQuery sqlQuery = new SQLQuery(connection, configuration)
    .from(userPath).where(idPath.eq(1l)).limit(10);
sqlQuery.setUseLiterals(true);    
String query = sqlQuery.getSQL(usernamePath).getSQL();

Если вы всегда просто хотите получить строку запроса SQL, переместите setUseLiterals из запроса в конфигурацию.

Что касается использования выражений Querydsl, рекомендуется использовать генерацию кода, описанную здесь, http://www.querydsl.com/static/querydsl/3.3.1/reference/html/ch02s03.html

Это сделает ваш код типичным, компактным и читаемым.

Если вы хотите попробовать Querydsl без генерации кода, вы можете заменить

Path<Object> userPath = new PathImpl<Object>(Object.class, variable);

с

Path<Object> userPath = new RelationalPathBase<Object>(Object.class, variable, schema, table);

Ответ 2

При работе с QueryDSL вы должны предоставить шаблон для платформы базы данных для построения запроса. Я вижу, вы уже делаете это здесь:

private SQLTemplates templates = new MySQLTemplates();
private Configuration configuration = new Configuration(templates); 

Чтобы имя схемы отображалось в сгенерированном запросе, единственным способом, который я нашел для этого, является (может быть, более простой способ) - расширить класс шаблона и явно вызвать this.setPrintSchema(true); внутри конструктора. Вот класс, который должен работать на MySql:

import com.mysema.query.sql.MySQLTemplates;

public class NewMySqlTemplates extends MySQLTemplates {

    public NewMySqlTemplates() {
        super('\\', false);
    }

    public NewMySqlTemplates(boolean quote) {
        super('\\', quote);
    }

    public NewMySqlTemplates(char escape, boolean quote) {
        super(escape, quote);
        this.setPrintSchema(true);
    }

}

Затем просто используйте этот класс NewMySqlTemplates вместо класса MySQLTemplates следующим образом:

private SQLTemplates templates = new NewMySQLTemplates();
private Configuration configuration = new Configuration(templates); 

У меня есть работа с использованием PostgresTemplates, поэтому у меня может быть опечатка или ошибка в классе NewMySqlTemplates выше, но вы должны иметь возможность заставить ее работать. Удачи!