【问题标题】:Spring ScriptUtils - Unterminated dollar quote in PostgreSQLSpring ScriptUtils - PostgreSQL 中未终止的美元报价
【发布时间】:2019-09-09 08:41:25
【问题描述】:

我正在使用以下 Java 代码运行 SQL 脚本:

@SpringBootApplication
public class Application implements CommandLineRunner {
  @Autowired
  DataSource ds;

  @Value("classpath:test.sql")
  Resource resource;

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    try {
      @Cleanup
      Connection c = ds.getConnection();
      ScriptUtils.executeSqlScript(c, resource);

    } catch (Exception e) {
      e.printStackTrace();
    }

  }

}

我使用的 Spring boot 版本是 2.1.7.RELEASE 并且 PostgreSQL 在本地 docker 镜像中运行,通过:

docker run --rm   --name pg-docker -e POSTGRES_PASSWORD=PASSWORD -d -p 5432:5432 -v postgresql:/var/lib/postgresql/data  postgres:11.3

我使用的 SQL 脚本是:

CREATE OR REPLACE FUNCTION totalRecords ()
RETURNS integer AS $total$
declare
  total integer;
BEGIN
   SELECT count(*) into total FROM COMPANY;
   RETURN total;
END;
$total$ LANGUAGE plpgsql; 

在我看来这是完全有效的并且在 PgAdmin 中运行正常。

不幸的是,我收到了来自 Java 的以下异常:

Caused by: org.postgresql.util.PSQLException: Unterminated dollar quote started at position 62 in SQL CREATE OR REPLACE FUNCTION totalRecords () RETURNS integer AS $total$ declare total integer. Expected terminating $$
    at org.postgresql.core.Parser.checkParsePosition(Parser.java:1274)
    at org.postgresql.core.Parser.parseSql(Parser.java:1173)
    at org.postgresql.core.Parser.replaceProcessing(Parser.java:1125)
    at org.postgresql.core.CachedQueryCreateAction.create(CachedQueryCreateAction.java:41)
    at org.postgresql.core.QueryExecutorBase.createQueryByKey(QueryExecutorBase.java:314)
    at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:289)
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:274)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:269)
    at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95)
    at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java)
    at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:488)
    ... 9 more

怎么了?请问我该如何解决?或者如果 ScriptUtils 无法从 Java 可靠地运行 PostgreSQL 脚本?

【问题讨论】:

    标签: java spring postgresql spring-jdbc


    【解决方案1】:

    终于我自己解决了。不确定我的解决方案是否是最好的想法。问题出在 ScriptUtils - 它通过 ScriptUtils.DEFAULT_STATEMENT_SEPARATOR 确定语句结束,即“;”。不幸的是,FUNCTION 命令包含各种“;”这是声明本身的一部分。所以解决方案是声明并使用另一个不干扰 PostgreSQL 语法的分隔符。就我而言,我使用了两个分号 - “;;”。所以我的陈述看起来像:

    CREATE OR REPLACE FUNCTION totalRecords ()
    RETURNS integer AS $total$
    declare
      total integer;
    BEGIN
       SELECT count(*) into total FROM COMPANY;
       RETURN total;
    END;
    $total$ LANGUAGE plpgsql;; 
    

    并且调用它的Java代码改为:

    ScriptUtils.executeSqlScript(c, new EncodedResource(resource, "UTF-8"), false, false, ScriptUtils.DEFAULT_COMMENT_PREFIX, ";;",
          ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER, ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER);
    

    【讨论】:

      【解决方案2】:

      正如here 所说,休眠似乎是它解析时的问题。将 $total$ 替换为 ' ,它应该可以工作:

      CREATE OR REPLACE FUNCTION totalRecords ()
      RETURNS integer AS '
      declare
        total integer;
      BEGIN
         SELECT count(*) into total FROM COMPANY;
         RETURN total;
      END;
      ' LANGUAGE plpgsql; 
      

      【讨论】:

        猜你喜欢
        • 2019-08-30
        • 2021-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-29
        • 2016-06-14
        • 1970-01-01
        相关资源
        最近更新 更多