错误:无法使用绑定参数定义物化视图。如何通过 JPA 创建物化视图?

问题描述 投票:0回答:1

我的目标是在运行时在 PostreSQL 数据库中创建不同的物化视图,我想使用 Spring JPA EntityManager 和 Hibernate。我在 stackoverflow 上研究了类似的问题,但没有一个能解决我的问题,我真的希望在这里得到建议。我使用 Spring Boot 3.3.3、Hibernate 6 和 PostrgreSQL。

我的问题是:如何使用不同类型的参数(视图名称、条件)配置本机sql查询,以在postgres数据库中成功创建新的物化视图?

我有一张桌子,问题是这样的:

create table if not exists question(
        id uuid primary key not null,
        type uuid not null, -- maps to Type table
        content text unique not null,
        grade int not null,
        created_at timestamp with time zone
);

我尝试使用类似下面示例的某种类型

Query query = entityManager.createNativeQuery(
        "create materialized view if not exists :name as" +
                " select * from question q" +
                " where" +
                " q.type in (:typesList)" +
                " and" +
                " q.grade <= :maxGrade" +
                " and" +
                " q.grade >= :minGrade"
)
.setParameter("name", name) // String name
.setParameter("typesList", list) // List<UUID> list
.setParameter("maxGrade", maxGrade) // Integer maxGrade
.setParameter("minGrade", minGrade); // Integer minGrade

query.executeUpdate();

但它执行时出现异常(此异常告诉我查询中第一个参数(

:name
)的位置):
JDBC exception executing SQL [create materialized view if not exists ? as select * from question q where q.type in (?,?) and q.grade <= ? and q.grade >= ?] [ERROR: syntax error at or near "$1"

在下一步中,我停止使用视图名称参数,我的查询如下所示:

Query query = entityManager.createNativeQuery(
        "create materialized view if not exists " + name + " as" +
                " select * from question q" +
                " where" +
                " q.type in (:typesList)" +
                " and" +
                " q.grade <= :maxGrade" +
                " and" +
                " q.grade >= :minGrade"
)
.setParameter("typesList", list) // List<UUID> list
.setParameter("maxGrade", maxGrade) // Integer maxGrade
.setParameter("minGrade", minGrade); // Integer minGrade

query.executeUpdate();

这也失败了,但有例外:

Caused by: org.postgresql.util.PSQLException: ERROR: materialized views may not be defined using bound parameters

最后唯一正确工作的情况是:

Query query = entityManager.createNativeQuery(
        "create materialized view if not exists " + name +" as" +
            " select * from question" +
            " where" +
            " type in (" + buildTypeCondition(list) + ")" +
            " and" +
            " grade <= " + (maxGrade) +
            " and" +
            " grade >= " + (minGrade)
);

//buildTypeCondition here creates a string like "'<uuid1>', '<uuid2>', ..."

但它的代码确实很糟糕,为了避免 SQL 注入,我需要摆脱将字符串参数直接注入 sql 查询的情况。

您能帮我一下吗,在这种情况下我应该如何正确使用参数?我应该如何从

IN (uuid, uuid, ...)
参数创建有效的
List<UUID>
SQL 条件?

java sql postgresql parameter-passing
1个回答
0
投票

DDL 语句不支持参数。您必须手动生成 SQL 并清理参数。

您不需要

EntityManager
,没有实体需要管理。使用
DataSource

在运行时生成物化视图听起来很粗略。并且不能轻松地与 Hibernate 一起工作。考虑不同的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.