Sql H2中通过PreparedStatement查询抛出异常:PreparedStatement不允许使用此方法;改用常规语句

Sql H2中通过PreparedStatement查询抛出异常:PreparedStatement不允许使用此方法;改用常规语句,sql,exception,select,h2,executequery,Sql,Exception,Select,H2,Executequery,在Java11中,当使用JDBC4访问数据库时,一个简单的查询在运行一个准备好的语句时失败 运行此线路时: try ResultSet rs=pstmt.executeQuery sql;{ …我得到这个错误: org.h2.jdbc.JdbcSQLException:准备好的语句不允许使用此方法;请使用常规语句。[90130-197] 我试着用这个,但是没有用 下面是一个完整的示例应用程序,位于一个.java文件中。您可以复制粘贴并自行运行 package com.basilbourque.e

在Java11中,当使用JDBC4访问数据库时,一个简单的查询在运行一个准备好的语句时失败

运行此线路时:

try ResultSet rs=pstmt.executeQuery sql;{ …我得到这个错误:

org.h2.jdbc.JdbcSQLException:准备好的语句不允许使用此方法;请使用常规语句。[90130-197]

我试着用这个,但是没有用

下面是一个完整的示例应用程序,位于一个.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();
        }

    }
}
两次传递SQL字符串 在PreparedStatement上,永远不会将SQL字符串传递给executeQuery方法。在未准备好的语句中传递SQL字符串,但在PreparedStatement中不传递。请注意JavaDoc for如何不带参数

所以你的台词是:

try ( ResultSet rs = pstmt.executeQuery( sql ) ; ) {
……应该是:

try ( ResultSet rs = pstmt.executeQuery() ; ) {
在准备语句时,您已经在该行上方传递了名为SQL的SQL字符串:

PreparedStatement pstmt = conn.prepareStatement( sql ) ;
由于名为pstmt的PreparedStatement已经保存了SQL语句,因此无需传递到executeQuery


这个错误可能是由于使用语句复制粘贴了一些代码,以便在使用PreparedStatement的其他代码中重复使用。

我担心您的答案,一个人们经常犯的错误,将隐藏在您的标题中,其中谈到H2数据库。顺便说一句,许多教程也犯了这个错误。@TimBiegeleisen感谢您的帮助反馈。我的问题实际上是针对H2的,因为在互联网上搜索H2的特定错误消息,不管最后是否有代码,都找不到任何有用的信息。所以我想在这里为子孙后代提供详细信息——当我忘记这一点,并在六个月内再次重复我的错误时,我也是如此。至于repeating我的错误…发生在今天,在这里我笑着读这页。在这里,进行投票。顺便说一句,这个问答完全值得在SO数据库中。