PreparedStatement语法存在的问题
PreparedStatement的问题来源于它的参数的语法,PreparedStatement语句的参数是匿名并被通过索引访问,如下代码所示:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name = ? or last_name = ?) and address = ?");
p.setString(1, name);
p.setString(2, name);
p.setString(3, address);
对于一两个小的查询来说,这不是问题,但是对于大量参数的查询,跟踪索引就会变得困难。开发者必须小心翼翼的阅读SQL语句并查找出对应的参数索引,如果一个参数被插入或被删除,所有的索引就要被重新命名,很显然,当这个被插入或删除的参数在最开始,而后面还有更多的参数的时候,或者查询被重新组织了,这两种情况都会导致很多麻烦。
解决方法?(Workarounds)
有一个方法可以解决重新命名索引,那就是使用一个计数器来跟踪索引,如下代码所示:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name = ? or last_name = ?) and address = ?");
int i = 1;
p.setString(i++, name);
p.setString(i++, name);
p.setString(i++, address);
这种方法对于某个参数被插入或者删除的情况来说,有很好的效果,但是代码依然可读性差,而且程序员依然要注意确保参数的顺序。
NamedParameterStatement
现在我们来看看NamedParameterStatement这个类,这个类和PreparedStatement的基本相同,除了一点,那就是不是用问号?来顶替索引,而是用一个变量来顶替索引,如下面的代码所示:
String query = "select * from people where (first_name = :name or last_name
= :name) and address = :address");
NamedParameterStatement p = new NamedParameterStatement(con, query);
p.setString("name", name);
p.setString("address", address);
这个类的内幕就是,NamedParameterStatement类做了一个转换,它使用HashMap将SQL语句种对应的变量转换成问号,然后再创建一个对应的PreparedStatement语句,并且保持了对应变量和索引的映射关系,这两个类是兼容的,所以你可以分别加以利用。
论性能
两者的性能的差别在于NamedParameterStatement多了一个转换的过程,但这个过程所消耗的性能是非常之小,经过本机的测试,执行一条简单的查询表的记录的语句,PreparedStatement花了332毫秒,而NamedParameterStatement则花了352毫秒。在加入缓存之后,已经没有任何区别。
总结
NamedParameterStatement作为PreparedStatement的代替是高效而且无需配置的,同时它的简便的接口也提高了程序员的效率,或者更重要的是,由于代码的可读性增强,维护会变得更加轻松。
附上代码:
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.util.*;
/**
* This class wraps around a {@link PreparedStatement} and allows the programmer to set parameters by name instead
* of by index. This eliminates any confusion as to which parameter index represents what. This also means that
* rearranging the SQL statement or adding a parameter doesn't involve renumbering your indices.
* Code such as this:
*
*
* Connection conn = getConnection();
* String sql = "select * from my_table where name=? or address=?";
* PreparedStatement p = conn.prepareStatement(sql);
* p.setString(1, "bob");
* p.setString(2, "123");
* ResultSet rs = p.executeQuery();
*
*
* Can be replaced with:
*
*
* Connection conn = getConnection();
* String sql = "select * from my_table where name=:name or address=:address";
* NamedParameterStatement p = new NamedParameterStatement(conn, sql);
* p.setString("name", "bob");
* p.setString("address", "123");
* ResultSet rs = p.executeQuery();
*
*/
public class NamedParameterStatement extends PreparedStatementWrapper {
private static final HashMap>> nameIndexCache = new HashMap>>();
private static final HashMap parsedSqlCache = new HashMap();
private final String parsedSql;
private final Map> nameIndexMap;
/**
* Creates a NamedParameterStatement. Wraps a call to
* c.{@link Connection#prepareStatement(java.lang.String) prepareStatement}.
* @param conn the database connection
* @param sql the parameterized sql
* @throws SQLException if the statement could not be created
*/
public NamedParameterStatement(Connection conn, String sql) throws SQLException {
if (nameIndexCache.containsKey(sql)) {
nameIndexMap = nameIndexCache.get(sql);
parsedSql = parsedSqlCache.get(sql);
} else {
nameIndexMap = new HashMap>();
parsedSql = parseNamedSql(sql, nameIndexMap);
nameIndexCache.put(sql, nameIndexMap);
parsedSqlCache.put(sql, parsedSql);
}
ps = conn.prepareStatement(parsedSql);
}
/**
* Returns the indexes for a parameter.
* @param name parameter name
* @return parameter indexes
* @throws IllegalArgumentException if the parameter does not exist
*/
private List getIndexes(String name) {
List indexes = nameIndexMap.get(name);
if (indexes == null) {
throw new IllegalArgumentException("Parameter not found: " + name);
}
return indexes;
}
/**
* Parses a sql with named parameters. The parameter-index mappings
* are put into the map, and the parsed sql is returned.
* @param sql sql with named parameters
* @return the parsed sql
*/
private static String parseNamedSql(String sql, Map> nameIndexMap) {
// I was originally using regular expressions, but they didn't work well for ignoring
// parameter-like strings inside quotes.
int length = sql.length();
StringBuffer parsedSql = new StringBuffer(length);
boolean inSingleQuote = false;
boolean inDoubleQuote = false;
int index = 1;
for (int i = 0; i < length; i++) {
char c = sql.charAt(i);
if (inSingleQuote) {
if (c == '\'') {
inSingleQuote = false;
}
} else if (inDoubleQuote) {
if (c == '"') {
inDoubleQuote = false;
}
} else {
if (c == '\'') {
inSingleQuote = true;
} else if (c == '"') {
inDoubleQuote = true;
} else if (c == ':' && i + 1 < length && Character.isJavaIdentifierStart(sql.charAt(i + 1))) {
int j = i + 2;
while (j < length && Character.isJavaIdentifierPart(sql.charAt(j))) {
j++;
}
String name = sql.substring(i + 1, j);
c = '?'; // replace the parameter with a question mark
i += name.length(); // skip past the end if the parameter
List indexList = nameIndexMap.get(name);
if (indexList == null) {
indexList = new LinkedList();
nameIndexMap.put(name, indexList);
}
indexList.add(index);
index++;
}
}
parsedSql.append(c);
}
return parsedSql.toString();
}
public void setArray(String name, Array value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setArray(index, value);
}
}
public void setAsciiStream(String name, InputStream value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setAsciiStream(index, value);
}
}
public void setAsciiStream(String name, InputStream value, int length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setAsciiStream(index, value, length);
}
}
public void setBigDecimal(String name, BigDecimal value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBigDecimal(index, value);
}
}
public void setBinaryStream(String name, InputStream value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBinaryStream(index, value);
}
}
public void setBinaryStream(String name, InputStream value, int length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBinaryStream(index, value, length);
}
}
public void setBinaryStream(String name, InputStream value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBinaryStream(index, value, length);
}
}
public void setBlob(String name, Blob value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBlob(index, value);
}
}
public void setBlob(String name, InputStream value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBlob(index, value);
}
}
public void setBlob(String name, InputStream value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBlob(index, value, length);
}
}
public void setBoolean(String name, boolean value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBoolean(index, value);
}
}
public void setByte(String name, byte value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setByte(index, value);
}
}
public void setBytes(String name, byte[] value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setBytes(index, value);
}
}
public void setCharacterStream(String name, Reader value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setCharacterStream(index, value);
}
}
public void setCharacterStream(String name, Reader value, int length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setCharacterStream(index, value, length);
}
}
public void setCharacterStream(String name, Reader value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setCharacterStream(index, value, length);
}
}
public void setClob(String name, Clob value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setClob(index, value);
}
}
public void setClob(String name, Reader value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setClob(index, value);
}
}
public void setClob(String name, Reader value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setClob(index, value, length);
}
}
public void setDate(String name, Date value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setDate(index, value);
}
}
public void setDate(String name, Date value, Calendar cal) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setDate(index, value, cal);
}
}
public void setDouble(String name, double value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setDouble(index, value);
}
}
public void setFloat(String name, float value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setFloat(index, value);
}
}
public void setInt(String name, int value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setInt(index, value);
}
}
public void setLong(String name, long value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setLong(index, value);
}
}
public void setNCharacterStream(String name, Reader value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNCharacterStream(index, value);
}
}
public void setNCharacterStream(String name, Reader value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNCharacterStream(index, value, length);
}
}
public void setNClob(String name, NClob value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNClob(index, value);
}
}
public void setNClob(String name, Reader value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNClob(index, value);
}
}
public void setNClob(String name, Reader value, long length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNClob(index, value, length);
}
}
public void setNString(String name, String value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNString(index, value);
}
}
public void setNull(String name, int sqlType) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setNull(index, sqlType);
}
}
public void setObject(String name, Object value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setObject(index, value);
}
}
public void setObject(String name, Object value, int targetSqlType) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setObject(index, value, targetSqlType);
}
}
public void setObject(String name, Object value, int targetSqlType, int scaleOrLength) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setObject(index, value, targetSqlType, scaleOrLength);
}
}
public void setRef(String name, Ref value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setRef(index, value);
}
}
public void setRowId(String name, RowId value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setRowId(index, value);
}
}
public void setShort(String name, short value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setShort(index, value);
}
}
public void setSQLXML(String name, SQLXML value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setSQLXML(index, value);
}
}
public void setString(String name, String value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setString(index, value);
}
}
public void setTime(String name, Time value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setTime(index, value);
}
}
public void setTime(String name, Time value, Calendar cal) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setTime(index, value, cal);
}
}
public void setTimestamp(String name, Timestamp value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setTimestamp(index, value);
}
}
public void setTimestamp(String name, Timestamp value, Calendar cal) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setTimestamp(index, value, cal);
}
}
@SuppressWarnings("deprecation")
public void setUnicodeStream(String name, InputStream value, int length) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setUnicodeStream(index, value, length);
}
}
public void setURL(String name, URL value) throws SQLException {
for (Integer index : getIndexes(name)) {
ps.setURL(index, value);
}
}
}
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.util.*;
public class PreparedStatementWrapper implements PreparedStatement {
protected PreparedStatement ps;
@Override
public T unwrap(Class iface) throws SQLException {
return ps.unwrap(iface);
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
return ps.executeQuery(sql);
}
@Override
public ResultSet executeQuery() throws SQLException {
return ps.executeQuery();
}
@Override
public boolean isWrapperFor(Class> iface) throws SQLException {
return ps.isWrapperFor(iface);
}
@Override
public int executeUpdate(String sql) throws SQLException {
return ps.executeUpdate(sql);
}
@Override
public int executeUpdate() throws SQLException {
return ps.executeUpdate();
}
@Override
public void setNull(int parameterIndex, int sqlType) throws SQLException {
ps.setNull(parameterIndex, sqlType);
}
@Override
public void close() throws SQLException {
ps.close();
}
@Override
public int getMaxFieldSize() throws SQLException {
return ps.getMaxFieldSize();
}
@Override
public void setBoolean(int parameterIndex, boolean x) throws SQLException {
ps.setBoolean(parameterIndex, x);
}
@Override
public void setByte(int parameterIndex, byte x) throws SQLException {
ps.setByte(parameterIndex, x);
}
@Override
public void setMaxFieldSize(int max) throws SQLException {
ps.setMaxFieldSize(max);
}
@Override
public void setShort(int parameterIndex, short x) throws SQLException {
ps.setShort(parameterIndex, x);
}
@Override
public int getMaxRows() throws SQLException {
return ps.getMaxRows();
}
@Override
public void setInt(int parameterIndex, int x) throws SQLException {
ps.setInt(parameterIndex, x);
}
@Override
public void setMaxRows(int max) throws SQLException {
ps.setMaxRows(max);
}
@Override
public void setLong(int parameterIndex, long x) throws SQLException {
ps.setLong(parameterIndex, x);
}
@Override
public void setEscapeProcessing(boolean enable) throws SQLException {
ps.setEscapeProcessing(enable);
}
@Override
public void setFloat(int parameterIndex, float x) throws SQLException {
ps.setFloat(parameterIndex, x);
}
@Override
public void setDouble(int parameterIndex, double x) throws SQLException {
ps.setDouble(parameterIndex, x);
}
@Override
public int getQueryTimeout() throws SQLException {
return ps.getQueryTimeout();
}
@Override
public void setQueryTimeout(int seconds) throws SQLException {
ps.setQueryTimeout(seconds);
}
@Override
public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
ps.setBigDecimal(parameterIndex, x);
}
@Override
public void setString(int parameterIndex, String x) throws SQLException {
ps.setString(parameterIndex, x);
}
@Override
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
ps.setBytes(parameterIndex, x);
}
@Override
public void cancel() throws SQLException {
ps.cancel();
}
@Override
public SQLWarning getWarnings() throws SQLException {
return ps.getWarnings();
}
@Override
public void setDate(int parameterIndex, Date x) throws SQLException {
ps.setDate(parameterIndex, x);
}
@Override
public void setTime(int parameterIndex, Time x) throws SQLException {
ps.setTime(parameterIndex, x);
}
@Override
public void clearWarnings() throws SQLException {
ps.clearWarnings();
}
@Override
public void setCursorName(String name) throws SQLException {
ps.setCursorName(name);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
ps.setTimestamp(parameterIndex, x);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
ps.setAsciiStream(parameterIndex, x, length);
}
@Override
public boolean execute(String sql) throws SQLException {
return ps.execute(sql);
}
@Override
@SuppressWarnings("deprecation")
public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
ps.setUnicodeStream(parameterIndex, x, length);
}
@Override
public ResultSet getResultSet() throws SQLException {
return ps.getResultSet();
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
ps.setBinaryStream(parameterIndex, x, length);
}
@Override
public int getUpdateCount() throws SQLException {
return ps.getUpdateCount();
}
@Override
public boolean getMoreResults() throws SQLException {
return ps.getMoreResults();
}
@Override
public void clearParameters() throws SQLException {
ps.clearParameters();
}
@Override
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
ps.setObject(parameterIndex, x, targetSqlType);
}
@Override
public void setFetchDirection(int direction) throws SQLException {
ps.setFetchDirection(direction);
}
@Override
public int getFetchDirection() throws SQLException {
return ps.getFetchDirection();
}
@Override
public void setObject(int parameterIndex, Object x) throws SQLException {
ps.setObject(parameterIndex, x);
}
@Override
public void setFetchSize(int rows) throws SQLException {
ps.setFetchSize(rows);
}
@Override
public int getFetchSize() throws SQLException {
return ps.getFetchSize();
}
@Override
public int getResultSetConcurrency() throws SQLException {
return ps.getResultSetConcurrency();
}
@Override
public boolean execute() throws SQLException {
return ps.execute();
}
@Override
public int getResultSetType() throws SQLException {
return ps.getResultSetType();
}
@Override
public void addBatch(String sql) throws SQLException {
ps.addBatch(sql);
}
@Override
public void clearBatch() throws SQLException {
ps.clearBatch();
}
@Override
public void addBatch() throws SQLException {
ps.addBatch();
}
@Override
public int[] executeBatch() throws SQLException {
return ps.executeBatch();
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
ps.setCharacterStream(parameterIndex, reader, length);
}
@Override
public void setRef(int parameterIndex, Ref x) throws SQLException {
ps.setRef(parameterIndex, x);
}
@Override
public void setBlob(int parameterIndex, Blob x) throws SQLException {
ps.setBlob(parameterIndex, x);
}
@Override
public void setClob(int parameterIndex, Clob x) throws SQLException {
ps.setClob(parameterIndex, x);
}
@Override
public Connection getConnection() throws SQLException {
return ps.getConnection();
}
@Override
public void setArray(int parameterIndex, Array x) throws SQLException {
ps.setArray(parameterIndex, x);
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
return ps.getMetaData();
}
@Override
public boolean getMoreResults(int current) throws SQLException {
return ps.getMoreResults(current);
}
@Override
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
ps.setDate(parameterIndex, x, cal);
}
@Override
public ResultSet getGeneratedKeys() throws SQLException {
return ps.getGeneratedKeys();
}
@Override
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
ps.setTime(parameterIndex, x, cal);
}
@Override
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return ps.executeUpdate(sql, autoGeneratedKeys);
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
ps.setTimestamp(parameterIndex, x, cal);
}
@Override
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
ps.setNull(parameterIndex, sqlType, typeName);
}
@Override
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
return ps.executeUpdate(sql, columnIndexes);
}
@Override
public void setURL(int parameterIndex, URL x) throws SQLException {
ps.setURL(parameterIndex, x);
}
@Override
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
return ps.executeUpdate(sql, columnNames);
}
@Override
public ParameterMetaData getParameterMetaData() throws SQLException {
return ps.getParameterMetaData();
}
@Override
public void setRowId(int parameterIndex, RowId x) throws SQLException {
ps.setRowId(parameterIndex, x);
}
@Override
public void setNString(int parameterIndex, String value) throws SQLException {
ps.setNString(parameterIndex, value);
}
@Override
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return ps.execute(sql, autoGeneratedKeys);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
ps.setNCharacterStream(parameterIndex, value, length);
}
@Override
public void setNClob(int parameterIndex, NClob value) throws SQLException {
ps.setNClob(parameterIndex, value);
}
@Override
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
ps.setClob(parameterIndex, reader, length);
}
@Override
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
return ps.execute(sql, columnIndexes);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
ps.setBlob(parameterIndex, inputStream, length);
}
@Override
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
ps.setNClob(parameterIndex, reader, length);
}
@Override
public boolean execute(String sql, String[] columnNames) throws SQLException {
return ps.execute(sql, columnNames);
}
@Override
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
ps.setSQLXML(parameterIndex, xmlObject);
}
@Override
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
ps.setObject(parameterIndex, x, targetSqlType, scaleOrLength);
}
@Override
public int getResultSetHoldability() throws SQLException {
return ps.getResultSetHoldability();
}
@Override
public boolean isClosed() throws SQLException {
return ps.isClosed();
}
@Override
public void setPoolable(boolean poolable) throws SQLException {
ps.setPoolable(poolable);
}
@Override
public boolean isPoolable() throws SQLException {
return ps.isPoolable();
}
@Override
public void closeOnCompletion() throws SQLException {
ps.closeOnCompletion();
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
ps.setAsciiStream(parameterIndex, x, length);
}
@Override
public boolean isCloseOnCompletion() throws SQLException {
return ps.isCloseOnCompletion();
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
ps.setBinaryStream(parameterIndex, x, length);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
ps.setCharacterStream(parameterIndex, reader, length);
}
@Override
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
ps.setAsciiStream(parameterIndex, x);
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
ps.setBinaryStream(parameterIndex, x);
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
ps.setCharacterStream(parameterIndex, reader);
}
@Override
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
ps.setNCharacterStream(parameterIndex, value);
}
@Override
public void setClob(int parameterIndex, Reader reader) throws SQLException {
ps.setClob(parameterIndex, reader);
}
@Override
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
ps.setBlob(parameterIndex, inputStream);
}
@Override
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
ps.setNClob(parameterIndex, reader);
}
}