Spring-Data QueryDSL JDBC:如何将查询结果映射到域对象?

Spring-Data + QueryDSL + JDBC: how to map the query results to the domain objects?

我正在考虑使用Spring-Data QueryDSL JDBC替换(或增强)当前使用的MyBatis。
我的原因是:

  • 列名的编译时检查
  • 从IDE进行SQL语句编译和自动完成的编译时检查
  • 能够针对将与实际数据库一起工作的相同代码在Java集合上编写单元测试,这比预先填充数据库要简单和快捷得多
  • 它比MyBatis更为简洁-在DAO层下无需单独的XxxMapper.java和XxxMapper.xml
  • 但是我看到了以下问题:

  • 没有用于将查询结果映射到域对象的基础结构。 QueryDSL的QBean和MappingProjection,Spring的BeanPropertyRowMapper和Spring-Data的OneToManyResultSetExtractor似乎太低了,请参见下文。
  • 没有开箱即用的会话/事务级缓存,这是MyBatis中免费提供的
  • 没有开箱即用的MyBatis免费提供的SQL语句和结果记录
  • 由于我要问的是一个问题,所以让我们集中讨论我认为最重要的问题。
    所以我的问题是:
    是否有任何便捷的解决方案可以将QueryDSL的SQLQuery结果映射到域对象,类似于MyBatis或JPA提供的功能?也就是说,基于某些简单配置(例如XML,注释或简单Java)的映射?

    我特别对以下内容感兴趣:

  • 将列映射到自定义类型,例如EmailAddress Java对象的String列
  • 将一组列映射到嵌入式对象,例如将{first_name,last_name}分组为FullName Java对象
  • 支持一对多关系,例如能够提取包含地址列表的Customer对象。
  • 总而言之,我需要一种简单的方法来从以下SQL查询中获取以下" Customer"类的一个或多个对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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 timeSt
        String content;
    }

    查询:

    1
    2
    3
    4
    5
    6
    7
    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);

    对我来说,理想的解决方案是重用MyBatis映射基础结构。
    另一个映射解决方案或自定义解决方案也是可以接受的。
    笔记:
    如果您显示以下替代方案,我也可以接受"否定"答案:

  • 具有与MyBatis相当的易用性和透明性-您只需检查代码即可始终知道执行哪个SQL
  • 允许完全控制已执行的SQL代码,尤其是允许轻松编写三种DAO方法来检索"客户":不带"地址"和" selfDescription"信息,仅带"地址"以及所有字段
  • 允许在编译时检查您的SQL代码
  • 不需要手动编码SQL中每个域类的映射。
  • 在上面的示例中,替代方法应该可以很好地工作。

    已考虑的解决方案:

    • MyBatis" Builder"类(http://mybatis.github.io/mybatis-3/statement-builders.html):不够,因为列名和表名仍然是字符串,因此违反了要求(3)
    • Spring-data JPA QueryDSL:如果您显示如何满足要求(1)和(2),并且没有提供更简单的解决方案,则可以选择

    Lukas Eder在这里对一个类似的问题给出了一个很好的答案:是否可以将MyBatis和QueryDSL / jOOQ结合?

    他对映射问题的答案是使用Java 8功能样式功能还是专用解决方案,例如modelmapper。

    他还提到了Spring JCache支持作为一种缓存解决方案以及该日志记录解决方案。