apache/shardingsphere · error · SQLFeatureNotSupportedException

addBatch sql in PreparedStatement

Error message

addBatch sql in PreparedStatement

What it means

SQLFeatureNotSupportedException('addBatch sql in PreparedStatement') thrown by AbstractUnsupportedOperationPreparedStatement.addBatch(String). The JDBC specification requires PreparedStatement.addBatch(String) to throw, because a PreparedStatement is created from one fixed SQL string; batching raw SQL belongs to Statement.addBatch. ShardingSphere marks the override final and implements only the no-arg addBatch().

Source

Thrown at jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationPreparedStatement.java:39

import java.io.Reader;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;

/**
 * Unsupported {@code PreparedStatement} methods.
 */
public abstract class AbstractUnsupportedOperationPreparedStatement extends AbstractStatementAdapter implements PreparedStatement {
    
    @Override
    public final void addBatch(final String sql) throws SQLException {
        throw new SQLFeatureNotSupportedException("addBatch sql in PreparedStatement");
    }
    
    @Override
    public final ResultSetMetaData getMetaData() throws SQLException {
        throw new SQLFeatureNotSupportedException("getMetaData");
    }
    
    @Override
    public final void setNString(final int parameterIndex, final String x) throws SQLException {
        throw new SQLFeatureNotSupportedException("setNString");
    }
    
    @Override
    public final void setNClob(final int parameterIndex, final NClob x) throws SQLException {
        throw new SQLFeatureNotSupportedException("setNClob");
    }
    
    @Override

View on GitHub (pinned to e952770a21)

Solutions

  1. Use the no-arg ps.addBatch() after setXXX(...) each iteration — ShardingSpherePreparedStatement implements it.
  2. If you must batch heterogeneous raw SQL strings, create a Statement (conn.createStatement()) and use its addBatch(String).
  3. Fix generic helpers to branch: Statement -> addBatch(sql), PreparedStatement -> addBatch().

Example fix

// before
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    for (Row r : rows) { ps.addBatch(sql); }
}

// after
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    for (Row r : rows) { ps.setInt(1, r.id); ps.addBatch(); }
    ps.executeBatch();
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate before batching: PreparedStatement takes no SQL
if (stmt instanceof PreparedStatement) { ((PreparedStatement) stmt).addBatch(); } else { stmt.addBatch(sql); }

Type guard

static void addToBatch(final Statement stmt, final String sql) throws SQLException {
    if (stmt instanceof PreparedStatement) { ((PreparedStatement) stmt).addBatch(); } else { stmt.addBatch(sql); }
}

Prevention

When it happens

Trigger: Calling ps.addBatch("INSERT ...") on a ShardingSphere PreparedStatement; typical of copy-pasted Statement batching code or generic batch helpers that accept (PreparedStatement, String) pairs.

Common situations: Refactoring legacy Statement batching into PreparedStatement code without removing the sql argument; generic DAO base classes calling addBatch(sql) for all statement types; JDBC tutorials' Statement examples reused verbatim.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/a47a1f8d6afd54bf. Report an issue: GitHub.