使用JPA调用本地Postgresql命令

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

我正在使用第三方库在数据库PgBulkInsert中进行批量插入。它需要插入通常需要30分钟并在30秒内执行的插入内容。我们注意到超时会导致磁盘使用率泄漏,但是我们发现执行table reindex似乎可以纠正此问题。我正在尝试使用我的JPA实体管理器执行本机更新。以下代码有效,但包含潜在的SQL注入漏洞。

@Stateless
public class ReindexService {
  @PersistenceContext(unitName = "my-ds")
  private EntityManager em;

  public void reindexTable(String table) {
    String queryStr = "REINDEX TABLE " + table;
    Query query = em.createNativeQuery(queryStr);
    query.executeUpdate();
  }
}

当我传递字符串“ alert”以索引警报表时,它会产生以下SQL输出

/* dynamic native SQL query */ REINDEX TABLE alert

当我尝试使用位置参数时,会产生SQL错误

String queryStr = "REINDEX TABLE ?";
Query query = em.createNativeQuery(queryStr);
query.setParameter(1, table);
query.executeUpdate();

这将产生以下错误输出

/* dynamic native SQL query */ REINDEX TABLE ?
SQL Error: 0, SQLState: 42601
ERROR: syntax error at or near "$1"
Position: 46

[尝试使用名称参数时出现类似错误

String queryStr = "REINDEX TABLE :table";
Query query = em.createNativeQuery(queryStr);
query.setParameter("table", table);
query.executeUpdate();

这将产生相同的错误

/* dynamic native SQL query */ REINDEX TABLE ?
SQL Error: 0, SQLState: 42601
ERROR: syntax error at or near "$1"
Position: 46

有人知道如何使用我的实体管理器以不添加SQL注入漏洞的方式调用本地Postgresql重新索引表命令吗?我正在使用Hibernate 5.3.6.Final,但希望使用非实现特定的解决方案。

我也尝试访问Connection并执行JDBC调用,这似乎给出了错误

final Session session = //get session from entity manager
session.doWork(conn -> {
  try (PreparedStatement stmt = conn.prepareCall(REINDEX TABLE ?)) {
    stmt.setString(1, table);
    stmt.execute();
  }
});

产生与上述相同的错误

SQL Error: 0, SQLState: 42601
ERROR: syntax error at or near "$1"
Position: 15
postgresql jpa
1个回答
0
投票

标识符不能作为参数传递。如果您不希望表名来自用户输入(听起来有些奇怪),则可以尝试使用要重新索引的所有表的枚举,然后将枚举值传递给服务(仅连接字符串) )。

如果您确实希望表名来自不受信任的来源,则可以尝试将标识符括在双引号中并转义现有的双引号。

PostgreSQL中还有一个函数quote_ident,可用于正确引用标识符。因此,您可以创建一个存储过程,该存储过程从JPA代码中获取常规参数,并使用quote_ident和EXECUTE构造的查询。

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