web-dev-qa-db-ja.com

querydslから完全にマテリアライズされたクエリを取得する方法

Querydslを使用して、動的スキーマの動的クエリを構築しようとしています。実際に実行するのではなく、クエリだけを取得しようとしています。

これまでのところ、2つの問題に直面しています。-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;
}
15
MickJ

スキーマ印刷を有効にするには、次のパターンを使用します

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

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クラスにタイプミスや間違いがあるかもしれませんが、機能させることができるはずです。幸運を!

0
David Fleeman