postgresql 我如何修改下面的代码,以便从JPA中的JsonBMap类型中指定一个特定的字段名?

jchrr9hc  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(146)

所以我尝试从JPA中的JsonBMap中排序asc/desc,我可以在我的Postgres控制台中轻松完成:

select e from employee e
         where data->'loan'->>'type' LIKE '%Car%'
order by data->'loan'->>'type' asc

字符串
请注意,data是我的JsonBMap名称,下面是我用于排序的代码:

private static void setOrderBy(Collection<String> orderBys, CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, From root, Map<String, Map<String, String>> jsonBMap) {
        final List<Order> orders = new ArrayList<>();
        criteriaQuery.distinct(true);
        var mapName = jsonBMap.keySet().stream().findFirst().orElse(null);
        var map = jsonBMap.get(mapName);

        orderBys.stream()
                .map(field -> {
                    var isFieldDesc = field.startsWith("-");
                    var fieldWithoutSign = isFieldDesc ? field.substring(1) : field;

                    if (map.get(fieldWithoutSign) != null) {
                        var value = map.get(fieldWithoutSign);
                        Expression<?>[] expressions = Stream.of(List.of(root.get(mapName)), getExpressions(value, criteriaBuilder))
                                .flatMap(List::stream)
                                .toArray(Expression<?>[]::new);
                        Expression<String> expression = criteriaBuilder.function("jsonb_extract_path_text", String.class, expressions);
                        return isFieldDesc ? criteriaBuilder.desc(expression) : criteriaBuilder.asc(expression);
                    } else {
                        String[] explodedPath = fieldWithoutSign.split("\\.");
                        Path<?> selection = explodedPathAsPath(root, explodedPath);
                        return isFieldDesc ? criteriaBuilder.desc(selection) : criteriaBuilder.asc(selection);
                    }
                }).forEach(orders::add);

        criteriaQuery.orderBy(orders);
    }


请注意,我甚至添加了配置,以在我的Postgres Config中注册下面的函数

registerFunction("jsonb_extract_path_text", new SQLFunctionTemplate(StringType.INSTANCE, "jsonb_extract_path_text(?1, ?2, ?3)"));


执行后:

criteriaQuery.multiselect(List.of(mainObject,order.getExpression));
TypedQuery<Object[]> query = entityManager.createQuery(criteriaQuery);
return query.getResultStream();

**query.getResultStream()**抛出以下错误:

Caused by: org.postgresql.util.PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
  Position: 739
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2505)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2241)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:310)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:447)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:368)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:158)
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:108)
    at io.agroal.pool.wrapper.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:76)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:57)


你能给点建议吗?

nwsw7zdq

nwsw7zdq1#

问题是在ORDER BY中使用的列在DISTINCT引用这个post中没有指定。如果你尝试运行这个,它会引发同样的错误。

select distinct e 
from employee e
where data->'loan'->>'type' LIKE '%Car%'
order by data->'loan'->>'type' asc

字符串
要解决这个问题,您可以在查询中删除distinct QueryHint
如果您仍然需要订购,让我们将其添加到您的选择中

select distinct e, data->'loan'->>'type' as loan_type
from employee e
where data->'loan'->>'type' LIKE '%Car%'
order by data->'loan'->>'type' asc

相关问题