MySQL ServerPreparedStatement查询

本文详细介绍了MySQL中ServerPreparedStatement执行查询的过程,包括查询包的组装、发送至Server、结果集的接收与转换等关键步骤。
JDBC驱动初始化-Mysql:[url]http://donald-draper.iteye.com/blog/2342010[/url]
JDBC连接的获取:[url]http://donald-draper.iteye.com/blog/2342011[/url]
Mysql负载均衡连接的获取:[url]http://donald-draper.iteye.com/blog/2342089[/url]
Mysql主从复制读写分离连接的获取:[url]http://donald-draper.iteye.com/blog/2342108[/url]
ConnectionImp创建MysqlIO :[url]http://donald-draper.iteye.com/blog/2342959[/url]
Mysql预编译SQL:[url]http://donald-draper.iteye.com/blog/2342960[/url]
MysqlSQL PreparedStatement的查询:[url]http://donald-draper.iteye.com/blog/2343083[/url]
MySQL ServerPreparedStatement查询:[url]http://donald-draper.iteye.com/blog/2343124[/url]
再前面说过PreparedStatement的查询,今天看一下ServerPreparedStatement的查询,
这篇文章要结合PreparedStatement的查询来理解。
//ServerPreparedStatement执行查询的时候,调用的是PreparedStatement的查询方法
//ServerPreparedStatement
 public ResultSet executeQuery()
throws SQLException
{
checkClosed();
ConnectionImpl locallyScopedConn = connection;
checkForDml(originalSql, firstCharOfStmt);
CachedResultSetMetaData cachedMetadata = null;
synchronized(locallyScopedConn.getMutex())
{
if(locallyScopedConn.useMaxRows())
{
if(hasLimitClause)
{
//没有分页语句的查询
results = executeInternal(maxRows, sendPacket, createStreamingResultSet(), true, metadataFromCache, false);
} else
{
if(maxRows <= 0)
executeSimpleNonQuery(locallyScopedConn, "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
else
executeSimpleNonQuery(locallyScopedConn, "SET OPTION SQL_SELECT_LIMIT=" + maxRows);
results = executeInternal(-1, sendPacket, doStreaming, true, metadataFromCache, false);
if(oldCatalog != null)
connection.setCatalog(oldCatalog);
}
} else
{
results = executeInternal(-1, sendPacket, doStreaming, true, metadataFromCache, false);
}
}
return results;
}

executeInternal此方法在PreparedStatement有实现,由于ServerPreparedStatement继承
PreparedStatement,重写了这个方法,我们来看ServerPreparedStatement的这个方法
public class ServerPreparedStatement extends com.mysql.jdbc.PreparedStatement
{
//执行查询,返回查询结果集
protected ResultSetInternalMethods executeInternal(int maxRowsToRetrieve, Buffer sendPacket, boolean createStreamingResultSet, boolean queryIsSelectOnly, Field metadataFromCache[], boolean isBatch)
throws SQLException
{
numberOfExecutions++;
//委托给serverExecute方法
return serverExecute(maxRowsToRetrieve, createStreamingResultSet, metadataFromCache);
}
}

//ServerPreparedStatement查询
private ResultSetInternalMethods serverExecute(int maxRowsToRetrieve, boolean createStreamingResultSet, Field metadataFromCache[])
throws SQLException
{
//获取互斥锁
Object obj = connection.getMutex();
JVM INSTR monitorenter ;
MysqlIO mysql;
Buffer packet;
long begin;
boolean logSlowQueries;
boolean gatherPerformanceMetrics;
StatementImpl.CancelTask timeoutTask;
//从连接获取MysqlIO
mysql = connection.getIO();
//从MysqlIO获取查询包
packet = mysql.getSharedSendPacket();
packet.clear();
packet.writeByte((byte)23);
packet.writeLong(serverStatementId);
boolean usingCursor = false;
if(connection.versionMeetsMinimum(4, 1, 2))
{
if(resultFields != null && connection.isCursorFetchEnabled() && getResultSetType() == 1003 && getResultSetConcurrency() == 1007 && getFetchSize() > 0)
{
packet.writeByte((byte)1);
usingCursor = true;
} else
{
packet.writeByte((byte)0);
}
packet.writeLong(1L);
}
int nullCount = (parameterCount + 7) / 8;
int nullBitsPosition = packet.getPosition();
for(int i = 0; i < nullCount; i++)
packet.writeByte((byte)0);

byte nullBitsBuffer[] = new byte[nullCount];
packet.writeByte(((byte)(sendTypesToServer ? 1 : 0)));
if(sendTypesToServer)
{
for(int i = 0; i < parameterCount; i++)
packet.writeInt(parameterBindings[i].bufferType);

}
for(int i = 0; i < parameterCount; i++)
{
if(parameterBindings[i].isLongData)
continue;
if(!parameterBindings[i].isNull)
storeBinding(packet, parameterBindings[i], mysql);
else
nullBitsBuffer[i / 8] |= 1 << (i & 7);
}

int endPosition = packet.getPosition();
packet.setPosition(nullBitsPosition);
packet.writeBytesNoNull(nullBitsBuffer);
packet.setPosition(endPosition);
begin = 0L;
logSlowQueries = connection.getLogSlowQueries();
gatherPerformanceMetrics = connection.getGatherPerformanceMetrics();
if(profileSQL || logSlowQueries || gatherPerformanceMetrics)
begin = mysql.getCurrentTimeNanosOrMillis();
resetCancelledState();
timeoutTask = null;
ResultSetInternalMethods resultsetinternalmethods;
if(connection.getEnableQueryTimeouts() && timeoutInMillis != 0 && connection.versionMeetsMinimum(5, 0, 0))
{
//如果启动延时查询,创建延时查询TimeTask,并通过ConnectionImpl的CancelTimer(Timer)去调度
timeoutTask = new StatementImpl.CancelTask(this, this);
connection;
ConnectionImpl.getCancelTimer().schedule(timeoutTask, timeoutInMillis);
}
//MysqlIO向Server发送查询命令
Buffer resultPacket = mysql.sendCommand(23, null, packet, false, null, 0);
long queryEndTime = 0L;
if(logSlowQueries || gatherPerformanceMetrics || profileSQL)
queryEndTime = mysql.getCurrentTimeNanosOrMillis();
if(timeoutTask != null)
{
timeoutTask.cancel();
if(timeoutTask.caughtWhileCancelling != null)
throw timeoutTask.caughtWhileCancelling;
timeoutTask = null;
}
synchronized(cancelTimeoutMutex)
{
if(wasCancelled)
{
SQLException cause = null;
if(wasCancelledByTimeout)
cause = new MySQLTimeoutException();
else
cause = new MySQLStatementCancelledException();
resetCancelledState();
throw cause;
}
}
//转化结果集,这个我们在PreparedStatement,看过,这里就不说了
ResultSetInternalMethods rs = mysql.readAllResults(this, maxRowsToRetrieve, resultSetType, resultSetConcurrency, createStreamingResultSet, currentCatalog, resultPacket, true, fieldCount, metadataFromCache);
return resultsetinternalmethods;
}

总结:
[color=blue]ServerPreparedStatement的查询与PreparedStatement的思想基本上一直的都是首先组装查询包,并通MysqlIO将包发送到Server,Server返回查询结果,MysqlIO将返回结果转换为ResultSetInternalMethods(ResultSetImpl),即ResultSet。[/color]
怎么在表ywgxgs_gdscsglhzhzfjcsfwmfmbjxx中解决这个问题 表输出.0 - Error batch inserting rows into table [ywgxgs_gdscsglhzhzfjcsfwmfmbjxx]. 表输出.0 - Errors encountered (first 10): 表输出.0 - 表输出.0 - 表输出.0 - Error updating batch 表输出.0 - Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation 'like' 表输出.0 - 表输出.0 - 表输出.0 - at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:349) 表输出.0 - at org.pentaho.di.trans.steps.tableoutput.TableOutput.processRow(TableOutput.java:125) 表输出.0 - at org.pentaho.di.trans.step.RunThread.run(RunThread.java:62) 表输出.0 - at java.lang.Thread.run(Thread.java:748) 表输出.0 - Caused by: org.pentaho.di.core.exception.KettleDatabaseBatchException: 表输出.0 - Error updating batch 表输出.0 - Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation 'like' 表输出.0 - 表输出.0 - at org.pentaho.di.core.database.Database.createKettleDatabaseBatchException(Database.java:1438) 表输出.0 - at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:296) 表输出.0 - ... 3 more 表输出.0 - Caused by: java.sql.BatchUpdateException: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation 'like' 表输出.0 - at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 表输出.0 - at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 表输出.0 - at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 表输出.0 - at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 表输出.0 - at com.mysql.cj.util.Util.handleNewInstance(Util.java:192) 表输出.0 - at com.mysql.cj.util.Util.getInstance(Util.java:167) 表输出.0 - at com.mysql.cj.util.Util.getInstance(Util.java:174) 表输出.0 - at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:224) 表输出.0 - at com.mysql.cj.jdbc.ServerPreparedStatement.executeBatchSerially(ServerPreparedStatement.java:384) 表输出.0 - at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchInternal(ClientPreparedStatement.java:435) 表输出.0 - at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:795) 表输出.0 - at org.pentaho.di.trans.steps.tableoutput.TableOutput.writeToTable(TableOutput.java:292) 表输出.0 - ... 3 more 表输出.0 - Caused by: java.sql.SQLException: Illegal mix of collations (utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation 'like' 表输出.0 - at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) 表输出.0 - at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) 表输出.0 - at com.mysql.cj.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:633) 表输出.0 - at com.mysql.cj.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:417) 表输出.0 - at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1098) 表输出.0 - at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1046) 表输出.0 - at com.mysql.cj.jdbc.ServerPreparedStatement.executeBatchSerially(ServerPreparedStatement.java:356) 表输出.0 - ... 6 more
最新发布
08-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值