4

I am considering to use Spring-Data + QueryDSL + JDBC to replace (or enhance) the currently used MyBatis.
My reasons are:

  1. Compile-time check of column names
  2. Compile-time check of SQL tatements and auto-completion from IDE
  3. Ability to write unit tests on Java Collections against the same code that will work against the actual DB, which is much simpler and faster than pre-populating a DB
  4. It is more concise than MyBatis – no need for a separate XxxMapper.java and XxxMapper.xml under the DAO layer

Yet I see the following problems:

  1. There is no infrastructure for mapping the query results to domain objects. QueryDSL's QBean and MappingProjection, Spring's BeanPropertyRowMapper and Spring-Data's OneToManyResultSetExtractor seem to be too low level, see below.
  2. No out of the box session/transaction-level cache which comes for free in MyBatis
  3. No out of the box SQL statement and result logging which comes for free in MyBatis

Since I am asking a single question let's concentrate on the mapping which I consider the most important problem.
So my question is:
Is there any convenient solution to map the QueryDSL's SQLQuery results to the domain object, similar to what MyBatis or JPA offer? That is, the mapping based on some simple configuration, be it XML, annotations, or simple Java?

In particular, I am interested in the following:

  1. Mapping a column to a custom type, e.g. a String column to an EmailAddress Java object
  2. Mapping a group of columns to an embedded object, such as e.g. grouping {first_name, last_name} into a FullName Java object
  3. Supporting one-to-many relationship, such as being able to extract a Customer object(s) containing a list of Addresses.

To summarize, I need an easy way to obtain one or many objects of the following 'Customer' class from the following SQL query:

class Customer {
    EmailAddress emailAddress;
    FullName fullName;
    Set<Address> addresses;
    Set<Comment> selfDescription;
}
class EmailAddress {
    private String address;
    EmailAddress(String address) {this.address = address; }
}
class FullName {
    String firstName, lastName;
}
class Address {
    String street, town, country;
}
class Comment {
    LocalDateTime timeStamp;
    String content;
}

Query:

query.from(qCustomer).
    leftJoin(qCustomer._addressCustomerRef, qAddress)).
    leftJoin(qCustomer._commentCustomerRed).
    getResults(
       qCustomer.email_address, qCustomer.first_name, qCustomer.last_name, 
       qAddress.street, qAddress.town, qAddress.country, 
       qComment.creation_time_stamp, qComment.content);

The ideal solution for me would be to reuse the MyBatis mapping infrastructure.
Another mapping solution or a custom one is also acceptable.
Note:
I could also accept "negative" answers if you show an alternative that:

  1. Possesses an ease of use and transparency comparable to that of MyBatis - you always know which SQL is executed by simply inspecting the code
  2. Allows full control over the executed SQL code, in particular, allows to easily write three DAO methods for retrieving 'Customer': without 'addresses' and 'selfDescription' information, just with 'addresses', and with all the fields
  3. Allows compile-time check of your SQL code
  4. Does not require hand-coding of mapping of every single domain class from SQL.

The alternative should work well on the example above.

Solutions already considered:

  • MyBatis 'Builder' class (http://mybatis.github.io/mybatis-3/statement-builders.html): not enough, since the column and table names are still Strings, so it violates requirement (3)
  • Spring-data + JPA + QueryDSL: might be an option if you show how the requirements (1) and (2) can be satisfied and if no simpler solution will be provided
Alexander
  • 2,761
  • 1
  • 28
  • 33

1 Answers1

0

Lukas Eder gave an excellent answer to a similar question here: Is it possible to combine MyBatis and QueryDSL/jOOQ?

His answer to the mapping question is to use either Java 8 functional style capabilities or a dedicated solution such as modelmapper.

He also mentioned Spring JCache support as a caching solution and this solution to the logging.

Community
  • 1
  • 1
Alexander
  • 2,761
  • 1
  • 28
  • 33