如何使用@Query 查询多列但不是所有列,但仍使用域数据模型来映射 Spring 数据 JDBC?

How to query more than one columns but not all columns with @Query but still use the Domain Data Model to map with 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 data 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 数据 JPA。它的 Spring 数据 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. 将您的 select 语句扩展为 , NULL as <column-name> 用于所有缺失的列。

    我不确定

    But this will still serialize the entire object with null values.

意味着这在某些方面对您不起作用。

  1. 指定 RowMapper.
  2. 您可以使用 class 来准确包含查询返回的字段。如果您想要一个由您的普通实体和 部分实体.
  3. 实现的接口,它甚至可以为其他列提供吸气剂

你写:

But the whole point of spring data JDBC is to avoid the tight coupling between pojo's data model and database schema.

这不太对。 Spring 数据 JDBC 的一个重要目标是在实体和 table 行之间没有 运行 时间连接。 这将需要代理或类似的东西,并带来很多复杂性。 但是实体和 table 之间的结构映射可能会更强(现在肯定是),因为 JPA 中可用的所有映射变体都带来了复杂性。 Spring Data JDBC 的主要目标是在概念上比 JPA 更简单。

你也问

Why not the EntityRowMapper is just mapping NULL to the properties which are not part of the query?

我不确定我在编码时是否积极考虑过它,但我不喜欢默认为 NULL 的想法,因为这很容易不小心不加载列,因为你别名有错字。

但我并不反对其他解决方案。 如果你有想法please create a feature request.