PrepareStatement之close

Posted by CaiJiahe on September 20, 2017

0x01 问题

	PreparedStatement stmt = conn.prepareStatement(sql);
	...
	stmt.executeBatch();
	stmt.close();
	conn.commit();

这么写数据无法持久化。

0x02 原因

@Override
public void close() throws SQLException {
	MySQLConnection locallyScopedConn = this.connection;

	if (locallyScopedConn == null) {
		return; // already closed
	}

	synchronized (locallyScopedConn.getConnectionMutex()) {
		if (this.isCached && isPoolable() && !this.isClosed) {
			clearParameters();
			this.isClosed = true;
			this.connection.recachePreparedStatement(this);
			return;
		}

		this.isClosed = false;
		realClose(true, true);
	}
}

// clearParameters内部调用
private void clearParametersInternal(boolean clearServerParameters) throws SQLException {
	boolean hadLongData = false;

	if (this.parameterBindings != null) {
		for (int i = 0; i < this.parameterCount; i++) {
			if ((this.parameterBindings[i] != null) && this.parameterBindings[i].isLongData) {
				hadLongData = true;
			}

			this.parameterBindings[i].reset();
		}
	}

	if (clearServerParameters && hadLongData) {
		// server端也重置该statement
		serverResetStatement();

		this.detectedLongParameterSwitch = false;
	}
}

实际上PrepareStatement的close方法会先清空Params,然后再缓存该statement。

0x03 解决办法

删除该close语句即可。