H2中通过PreparedStatement查询抛出异常:This method is not allowed for a prepared statement;改为使用常规语句
Query through PreparedStatement in H2 throws exception: This method is not allowed for a prepared statement; use a regular statement instead
在使用 JDBC 4 访问 Java 11 中的 H2 数据库时,当 运行 通过准备好的语句时,简单查询失败。
当运行宁此行时:
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 ) ;
由于名为 pstmt
的 PreparedStatement
已经包含您的 SQL 语句,因此无需传递到 executeQuery
.
这个错误可能是使用 Statement
复制粘贴某些代码以在其他使用 PreparedStatement
的代码中重用的结果。
在使用 JDBC 4 访问 Java 11 中的 H2 数据库时,当 运行 通过准备好的语句时,简单查询失败。
当运行宁此行时:
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 ) ;
由于名为 pstmt
的 PreparedStatement
已经包含您的 SQL 语句,因此无需传递到 executeQuery
.
这个错误可能是使用 Statement
复制粘贴某些代码以在其他使用 PreparedStatement
的代码中重用的结果。