sql - H2中通过PreparedStatement查询抛出异常: This method is not allowed for a prepared statement; use a regular statement instead

标签 sql exception select h2 executequery

在使用 JDBC 4 访问 H2 时通过准备好的语句运行简单查询失败Java 11 中的数据库。

运行这条线时:

try ( ResultSet rs = pstmt.executeQuery( sql ) ; ) {

…我收到这个错误:

org.h2.jdbc.JdbcSQLException: This method is not allowed for a prepared statement; use a regular statement instead. [90130-197]

我尝试使用 H2 Error Analyzer , 但没有帮助。

这是一个完整的示例应用程序,位于单个 .java 文件中。您可以自己复制粘贴并运行。

package com.basilbourque.example.work.basil.example.h2.pstmt_query;

import org.h2.jdbcx.JdbcDataSource;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class App {
    public static void main ( String[] args ) {
        App app = new App();
        app.doIt();
    }

    private void doIt ( ) {

        // Create database.
        try {
            Class.forName( "org.h2.Driver" );
        } catch ( ClassNotFoundException e ) {
            e.printStackTrace();
        }
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL( "jdbc:h2:mem:pstmt_query_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
        dataSource.setUser( "scott" );
        dataSource.setPassword( "tiger" );

        // Create table.
        try (
                Connection conn = dataSource.getConnection() ;
                Statement stmt = conn.createStatement() ;
        ) {
            String sql = "CREATE TABLE person_ ( \n" +
                    " pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , \n" +
                    " name_ VARCHAR NOT NULL \n" +
                    ");";
            System.out.println( sql );
            stmt.execute( sql );
        } catch ( SQLException e ) {
            e.printStackTrace();
        }

        // Query table.
        List < UUID > list = new ArrayList <>();
        String sql = "SELECT * FROM person_ WHERE name_ = ? ;";
        try (
                Connection conn = dataSource.getConnection() ;
                PreparedStatement pstmt = conn.prepareStatement( sql ) ;
        ) {
            String name = "Wendy Melvoin";
            pstmt.setString( 1 , name );
            try ( ResultSet rs = pstmt.executeQuery( sql ) ; ) {  // org.h2.jdbc.JdbcSQLException: This method is not allowed for a prepared statement; use a regular statement instead. [90130-197]
                while ( rs.next() ) {
                    UUID pkey = rs.getObject( "pkey_" , UUID.class );
                    list.add( pkey );
                }
            }

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

    }
}

异常报告:

org.h2.jdbc.JdbcSQLException: This method is not allowed for a prepared statement; use a regular statement instead. [90130-197]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.message.DbException.get(DbException.java:144)
    at org.h2.jdbc.JdbcPreparedStatement.executeQuery(JdbcPreparedStatement.java:302)
    at com.basilbourque.example.work.basil.example.h2.pstmt_query.App.doIt(App.java:53)
    at com.basilbourque.example.work.basil.example.h2.pstmt_query.App.main(App.java:13)

最佳答案

两次传递 SQL 字符串

PreparedStatement 上,您永远不会将 SQL 字符串传递给 executeQuery 方法。您在未准备的 Statement 中执行此操作,但不是 PreparedStatement。注意 PreparedStatement::executeQuery 的 JavaDoc没有争论。

所以你的台词:

try ( ResultSet rs = pstmt.executeQuery( sql ) ; ) {

……应该是:

try ( ResultSet rs = pstmt.executeQuery() ; ) {

当您准备语句时,您已经在该行上方传递了名为 sql 的 SQL 字符串:

PreparedStatement pstmt = conn.prepareStatement( sql ) ;

由于名为 pstmtPreparedStatement 已经保存了您的 SQL 语句,因此无需传递给 executeQuery

此错误可能是使用 Statement 复制粘贴某些代码以在其他使用 PreparedStatement 的代码中重用的结果。

关于sql - H2中通过PreparedStatement查询抛出异常: This method is not allowed for a prepared statement; use a regular statement instead,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53919831/

相关文章:

sql - 通过 SQL 语句获取表和列的定义

c# - SQL Server/Entity Framework - 如何按随机数排序然后在以后重现结果?

python - 从字符串列表中选择合适的选项

mysql - MySQL 中的 SELECT 问题

java - 在 Java 中使用 try catch 的最终实体

mysql - 如何在 MySQL 字段中选择以逗号分隔的字符串中的单词?

mysql - 加入只显示一条记录

mysql - 从查询的 AS 部分中选择的 WHERE 子句

javascript - 如何抑制javascript异常?

debugging - 什么会导致 ARM MemManage 异常且 MMSFR 寄存器中的所有位均为零?