先直接上源码:
@Override
public java.sql.ResultSet getGeneratedKeys() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.retrieveGeneratedKeys) {
throw SQLError.createSQLException(Messages.getString("Statement.GeneratedKeysNotRequested"), MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
if (this.batchedGeneratedKeys == null) {
if (this.lastQueryIsOnDupKeyUpdate) {
return this.generatedKeysResults = getGeneratedKeysInternal(1);
}
return this.generatedKeysResults = getGeneratedKeysInternal();
}
String encoding = this.session.getServerSession().getCharacterSetMetadata();
int collationIndex = this.session.getServerSession().getMetadataCollationIndex();
Field[] fields = new Field[1];
fields[0] = new Field("", "GENERATED_KEY", collationIndex, encoding, MysqlType.BIGINT_UNSIGNED, 20);
this.generatedKeysResults = this.resultSetFactory.createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
new ResultsetRowsStatic(this.batchedGeneratedKeys, new DefaultColumnDefinition(fields)));
return this.generatedKeysResults;
}
}
protected ResultSetInternalMethods getGeneratedKeysInternal(long numKeys) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
String encoding = this.session.getServerSession().getCharacterSetMetadata();
int collationIndex = this.session.getServerSession().getMetadataCollationIndex();
Field[] fields = new Field[1];
fields[0] = new Field("", "GENERATED_KEY", collationIndex, encoding, MysqlType.BIGINT_UNSIGNED, 20);
ArrayList<Row> rowSet = new ArrayList<>();
long beginAt = getLastInsertID();
if (this.results != null) {
String serverInfo = this.results.getServerInfo();
//
// Only parse server info messages for 'REPLACE' queries
//
if ((numKeys > 0) && (this.results.getFirstCharOfQuery() == 'R') && (serverInfo != null) && (serverInfo.length() > 0)) {
numKeys = getRecordCountFromInfo(serverInfo);
}
if ((beginAt != 0 /* BIGINT UNSIGNED can wrap the protocol representation */) && (numKeys > 0)) {
for (int i = 0; i < numKeys; i++) {
byte[][] row = new byte[1][];
if (beginAt > 0) {
row[0] = StringUtils.getBytes(Long.toString(beginAt));
} else {
byte[] asBytes = new byte[8];
asBytes[7] = (byte) (beginAt & 0xff);
asBytes[6] = (byte) (beginAt >>> 8);
asBytes[5] = (byte) (beginAt >>> 16);
asBytes[4] = (byte) (beginAt >>> 24);
asBytes[3] = (byte) (beginAt >>> 32);
asBytes[2] = (byte) (beginAt >>> 40);
asBytes[1] = (byte) (beginAt >>> 48);
asBytes[0] = (byte) (beginAt >>> 56);
BigInteger val = new BigInteger(1, asBytes);
row[0] = val.toString().getBytes();
}
rowSet.add(new ByteArrayRow(row, getExceptionInterceptor()));
beginAt += this.connection.getAutoIncrementIncrement();
}
}
}
ResultSetImpl gkRs = this.resultSetFactory.createFromResultsetRows(ResultSet.CONCUR_READ_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
new ResultsetRowsStatic(rowSet, new DefaultColumnDefinition(fields)));
return gkRs;
}
}
这里可以看出两个方法都是有锁的,所以线程是安全的。
这里有一个很美妙的东西,那就是无论你生成的主键有多小,他会强制使用BigInteger。这样的好处是让你主键空间直接最大化、避免数据不够大的溢出。
在此记录一下开发的生活的点滴!