Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get fully materialized query from querydsl

I am trying to use querydsl for building dynamic queries for dynamic schemas. I am trying to get just the query instead of having to actually execute it.

So far I have faced two issues: - The schema.table notation is absent. Instead I only get the table name. - I have been able to get the query but it separates out the variables and puts '?' instead which is understandable. But I am wondering if there is some way to get fully materialized query including the parameters.

Here is my current attempt and result(I am using MySQLTemplates to create the configuration):

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;

And what I get is:

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

What I wanted to get was:

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

Update: I came up with this sort of hack to get parameters materialized(Not ideal and would love better solution) But still could not get Schema.Table notation to work:

Hack follows. Please suggest cleaner QueryDsl way of doing it:

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;
}
like image 294
MickJ Avatar asked Feb 10 '14 22:02

MickJ


People also ask

How do I create queries with querydsl?

To create queries with Querydsl you need to instantiate variables and Query implementations. We will start with the variables. Let's assume that your project has the following domain type: Querydsl will generate a query type with the simple name QCustomer into the same package as Customer.

How do I use querydsl with Maven?

To use it, you must generate Querydsl query types for your SQL schema. This can be done for example with the following Maven configuration: When the query types have successfully been generated into the location of your choice, you can use them in your queries. List<Tuple> rows = query.select (cat.all ()).from (cat).fetch (); 2.3. Querying SQL

How to use querydsl-collections without generated query types?

Querying Collections The querydsl-collections module can be used with generated query types and without. The first section describes the usage without generated query types: 2.8.1. Usage without generated query types To use querydsl-collections without generated query types you need to use the Querydsl alias feature. Here are some examples.

Does querydsl support native SQL in JPA?

Querydsl supports Native SQL in JPA via the JPASQLQuery class. To use it, you must generate Querydsl query types for your SQL schema. This can be done for example with the following Maven configuration: When the query types have successfully been generated into the location of your choice, you can use them in your queries.


1 Answers

To enable schema printing use the following pattern

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

SQLTemplates subclasses were used before, but since some time the builder pattern is the official way to customize the templates http://www.querydsl.com/static/querydsl/3.3.1/reference/html/ch02s03.html#d0e904

And to enable direct serialization of literals use

//configuration level
configuration.setUseLiterals(true);

//query level
configuration.setUseLiterals(true);

Here is a full example

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

If you always just want the SQL query string out, move setUseLiterals from query to configuration.

Concerning the usage of Querydsl expressions the usage of code generation like documented here is advised http://www.querydsl.com/static/querydsl/3.3.1/reference/html/ch02s03.html

It will make your code typesafe, compact and readable.

If you want to try Querydsl without code generation you can replace

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

with

Path<Object> userPath = new RelationalPathBase<Object>(Object.class, variable, schema, table);
like image 142
Timo Westkämper Avatar answered Sep 28 '22 01:09

Timo Westkämper