h2 数据库的"列计数不匹配" 在 Spring-Boot @DataJpaTest中使用投影选择查询



我有一个Spring-Boot应用程序,其中包含一些使用内容投影的本机查询。它在生产中运行Postgres并且工作正常。我正在尝试使用@DataJpaTest和 h2 内存数据库为存储库设置集成测试,但我使用内容投影的查询失败,驱动程序中的 JdbcSQLException :

org.h2.jdbc.JdbcSQLException:列计数不匹配

我已成功保存到 TestEntityManager,因此数据库中有记录,但我无法通过存储库方法调用 SELECT。它在 Postgres 的生产中正常工作 - 这是对 h2 的限制吗,是否有我可以应用的解决方法以便我可以正确测试它?

存储库方法如下所示(一个内部连接,where 子句中的两个参数,表名和列更改以保护有罪者):

public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
@Query(nativeQuery = true,
value = "SELECT order.id, order.total, pizza.name " +
"FROM example.order " +
"INNER JOIN example.pizza USING (pizza_id) " +
"WHERE order.customer_id = :custId " +
"AND order.order_date = :orderDate ",
countQuery = "SELECT count(order.id) " +
"FROM example.order " +
"INNER JOIN example.pizza USING (pizza_id) " +
"WHERE order.customer_id = :custId " +
"AND order.order_date = :orderDate")
<T> Page<T> findAllByCustIdAndOrderDate(String custId, OffsetDateTime orderDate, Pageable paging, Class<T> type);
}

投影如下所示:

public interface PizzaOrderProjection {
Long getId();
Double getTotal();
String getName();
}

当我调用findAllByCustIdAndOrderDate时触发异常,它打印的 SQL 语句导致它是 SELECT。它打印的 SELECT 看起来完全正常:

Hibernate: 
/* dynamic native SQL query */ SELECT
order.id,
order.total,
pizza.name 
FROM
example.order 
INNER JOIN
example.pizza USING (pizza_id) 
WHERE
order.customer_id = ? 
AND order.order_date = ?  limit ?
2019-04-09 12:42:18.704  WARN 17568 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 21002, SQLState: 21S02
2019-04-09 12:42:18.708 ERROR 17568 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column count does not match; SQL statement:

事实证明,错误消息实际上与潜在问题无关

H2 数据库不支持inner join子句上的using关键字,仅支持on关键字。

此问题已通过将内部联接更改为改用on来解决,如下所示:

public interface OrderRepository extends PagingAndSortingRepository<Order, Long> {
@Query(nativeQuery = true,
value = "SELECT order.id, order.total, pizza.name " +
"FROM example.order " +
"INNER JOIN example.pizza ON order.pizza_id = pizza.pizza_id " +
"WHERE order.customer_id = :custId " +
"AND order.order_date = :orderDate ",
countQuery = "SELECT count(order.id) " +
"FROM example.order " +
"INNER JOIN example.pizza ON order.pizza_id = pizza.pizza_id " +
"WHERE order.customer_id = :custId " +
"AND order.order_date = :orderDate")
<T> Page<T> findAllByCustIdAndOrderDate(String custId, OffsetDateTime orderDate, Pageable paging, Class<T> type);
}

此更改使查询在 postgres 和 h2 中都有效。

最新更新