如何使用@Query查询多个列而不是所有列,但仍使用Domain Data Model映射Spring Data JDBC?

时间:2019-03-13 16:37:31

标签: spring-data-jdbc

我的数据模型是

 @Getter
 @Setter
 public class Customer {
   @Id private ID id;
   @CreatedDate protected Instant createdAt;
   @LastModifiedDate protected Instant updatedAt;
   @CreatedBy protected String createdBy;
   @LastModifiedBy protected String updatedBy;
   @Version protected Long version;
   private UUID orderId;
   private String offer;
}

我的存储库是

public interface CustomerRepository extends CrudRepository<Customer, UUID> {

@Query(
        "SELECT ID, Offer  FROM Customer WHERE orderId = :orderId ")
List<Customer> findCustomerByOrderId(
        @Param("orderId") UUID orderId);
}

这将导致出现异常'orderId column not found [42122-190]'。因此,Spring希望您始终查询所有列。我知道,使用JPA,我们在实体和数据模式之间建立了牢固的映射。但是,Spring数据JDBC的全部目的是避免POJO的数据模型与数据库模式之间的紧密耦合。为什么EntityRowMapper只是将NULL映射到不属于查询的属性?

是否有一种方法可以告诉所使用的RowMapper,以忽略不属于查询的属性?为这些简单的查询创建单独的RowMapper似乎是很多不必要的工作。

我仍然可以通过更改查询来解决此问题,例如

@Query(
        "SELECT ID, Offer, OrderId, null as CreatedAt, null as CreatedBy, null as UpdatedAt, null as UpdatedBy, null as Version  FROM Customer  WHERE orderId = :orderId ")

但这仍将使用空值序列化整个对象。我在这里想念一些明显的东西吗?

注意这不是Spring Data JPA。它的Spring Data JDBC。

修改 进一步研究它,异常是来自h2数据库库。

Caused by: org.h2.jdbc.JdbcSQLException: Column "orderid" not found [42122-190]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.jdbc.JdbcResultSet.getColumnIndex(JdbcResultSet.java:3129)
at org.h2.jdbc.JdbcResultSet.get(JdbcResultSet.java:3217)
at org.h2.jdbc.JdbcResultSet.getObject(JdbcResultSet.java:522)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getObject(HikariProxyResultSet.java)
at org.springframework.data.jdbc.core.EntityRowMapper.readFrom(EntityRowMapper.java:127)

1 个答案:

答案 0 :(得分:2)

至少现在不能。

有三种解决方案,您已经指出其中两种:

  1. 为所有缺少的列用, NULL as <column-name>扩展选择语句。

    我不确定是否

      

    但这仍将使用空值序列化整个对象。   表示这不适用于您。

  2. 指定一个RowMapper

  3. 您可以使用完全包含查询返回的字段的类。如果您要同时由普通实体和部分实体实现的接口,它甚至可以为其他列提供吸气剂。

您写:

  

但是,Spring数据JDBC的全部目的是避免pojo的数据模型与数据库模式之间的紧密耦合。

这不太正确。 Spring Data JDBC的一个重要目标是在实体和表行之间没有运行时连接。 这将需要代理或类似代理,并带来很多复杂性。 但是,由于JPA中可用的所有映射变体都带来了复杂性,因此实体与表之间的结构化映射可能会变得更强大(并且现在肯定如此)。 而且,Spring Data JDBC的主要目标是在概念上比JPA更简单。

您还问

  

为什么EntityRowMapper只是将NULL映射到不属于查询的属性?

我不确定在编写代码时是否会积极考虑它,但是我不喜欢默认为NULL的想法,因为这样会很容易意外地不加载列,因为您有一个别名中有错字。

但是我不反对其他解决方案。 如果您有一个想法please create a feature request