我当前正在寻找一个解决方案
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter with that position [1] did not exist;
我当前的@Query
注释是:
@Query(
nativeQuery = true,
value = "SELECT * FROM thgcop_order_placement WHERE "order_info" @> '{"parentOrderNumber":" :param "}'")
我猜position [1] did not exist
来自双引号加上双引号加单Quote。
我该如何使这项工作?
查询使用Postgres JSONB
数据类型。列定义是ORDER_INFO JSONB
以下本机查询在Postgres客户端中工作正常:
SELECT * FROM thgcop_order_placement
WHERE "order_info" @> '{"parentOrderNumber":"ORD123"}'
以上除了下面的我都不适用于我,
服务层代码: -
OrderInfo orderInfo = new OrderInfo();
orderInfo.setParentOrderNumber("ORD123");
....
String param = objectMapper.writeValueAsString(orderInfo);
List<Order> list = jpaRepository.getByParentOrderNumber(param);
jparepository.java代码: -
@Query(nativeQuery = true, value = "select * from thgcop_order_placement where order_info @> CAST(:condition as jsonb)")
List<Order> getByParentOrderNumber(@Param("condition") String parentOrderNumber);
这就是我实现结果的方式。我希望这对所有热情 !!
都会有所帮助谢谢大家的帮助!
tl; dr :首先使其与bind参数和普通JDBC一起使用。然后转到Spring数据,可能会倒在自定义实现上。
您在这里在许多层面上都面临问题。
-
让我们从现在忽略春季数据开始。您显示的语句与您尝试使用弹簧数据构建的语句非常不同,因为它不包含绑定变量。所以而不是
SELECT * FROM thgcop_order_placement WHERE "order_info" @> '{"parentOrderNumber":"ORD123"}'
我们应该将其与
进行比较SELECT * FROM thgcop_order_placement WHERE "order_info" @> '{"parentOrderNumber": ? }'
请注意,我们正在失去引号,因为它们表示字符串,但我们没有提供字符串,而是一个绑定参数。
-
我没有发现任何迹象表明您可以在JSON表达式的某些部分中使用绑定参数。因此,我们需要使用上面的语句,而不是上述语句:
SELECT * FROM thgcop_order_placement WHERE "order_info" @> ?
当然,绑定参数应包含完整的JSON表达式
-
不幸的是,这似乎不起作用,因为现在Postgres认为bind参数a
VARCHAR
而不是JSON表达式。请参阅https://blog.2ndquadrant.com/processing-json/。我认为正确的版本应该是SELECT * FROM thgcop_order_placement WHERE "order_info" @> ?::json
,但我也无法工作。
-
在任何情况下,您都可以将参数转换为JSON结构。通常,我建议对此使用SPEL表达式。但这行不通,因为弹簧数据会扼杀Spel表达中所需的卷曲括号,并将其视为Spel表达式的末端。
-
如果您得到这样的东西可以使用简单的JDBC连接或
JdbcTemplate
工作,则可以开始考虑@Query
注释。@Query( value= "SELECT * FROM thgcop_order_placement WHERE "order_info @> :name::json", nativeQuery = true)
这可能会触发更多问题,因为春季数据将考虑参数名称的::json
部分。如果是这种情况,您必须退回自定义实现。
我进行了几个实验,您可以在这里查看和玩耍。
尝试绑定参数如下
@Query(nativeQuery = true, value = "SELECT * FROM thgcop_order_placement"
+ " WHERE "order_info" @> '{"parentOrderNumber":" ?1 "}'")
我也陷入了一段时间。似乎Springboot以字符串格式解析查询时弄乱了。但是,这是我发现的解决方案,该解决方案将直接用作存储库中的本机查询:
- 由于
order_info
是jsonb
类型的,因此搜索的值可以施放为JSONB值。 - 要搜索的值:
{"parentOrderNumber":"ORD123"}
- 让我们逃脱由Java解析的整个字符串。
-
String searchString = "{"parentOrderNumber":"ORD123"}"
- 现在,让我们以春季可以理解的方式键入Postgres查询。
@Query(
value = "SELECT * from thgcop_order_placement where ((?1\:\:jsonb) <@ (order_info\:\:jsonb))",
nativeQuery=true
)
List<Order> getByParentOrderNumber(String searchString);
在哪里,
- Spring将用
searchString
的值代替?1
,如上所述。 -
::
是使用的类型运算符,我们明确将传递的参数(searchString
)分类到jsonb
中。因此,在尝试进行搜索之前,将值{"parentOrderNumber":"ORD123"}
转换为jsonb
。 - 此外,
order_info
列的值也明确类型为jsonb
。 - 现在,当两个项目(要搜索的值和列)是相同的数据类型时,我们可以使用
<@
操作员检查搜索字符串是否包含在列值中。
在服务级别,我们只需要这样做:
String orderNumber = "-- some order value e.g. ORD123 --"
String searchString = "{"parentOrderNumber":"" + orderNumber + ""}"
List<Order> list = jpaRepository.getByParentOrderNumber(searchString);
有关Postgres JSON操作员的更多详细信息可以在此处的官方文档中找到:https://www.postgresql.org/docs/9.5/functions-json.html