Last_insert_id()是MYSQL提供的返回当前客户端最后一个insert或update查询中设置为AUTO_INCREMENT列的值 Last_insert_id()不受其他客户端影响,所以是线程安全的,当前客户端只能拿到当前客户端的最新值,不需加锁处理 mybatis中的userGeneratedKeys="true" keyProperty="id"获取自增id的源码: SimpleStatementHandler: 1 public int update(Statement statement) 2 throws SQLException { 3 String sql = boundSql.getSql(); 4 Object parameterObject = boundSql.getParameterObject(); 5 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); 6 int rows; 7 if (keyGenerator instanceof Jdbc3KeyGenerator) { //使用Jdbc3KeyGenerator类型得到自增主键 8 statement.execute(sql, Statement.RETURN_GENERATED_KEYS); 9 rows = statement.getUpdateCount(); 10 keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); 11 } else if (keyGenerator instanceof SelectKeyGenerator) { //使用selectKeyGenerator(<selectKey></selectKey>), 对于MYSQL则使用 select LAST_INSERT_ID() 来实现获取自增主键ID 12 statement.execute(sql); 13 rows = statement.getUpdateCount(); 14 keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); 15 } else { 16 statement.execute(sql); 17 rows = statement.getUpdateCount(); 18 } 19 return rows; 20 } 1. JDBC3KeyGenerator 1 public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { 2 List<Object> parameters = new ArrayList<Object>(); 3 parameters.add(parameter); 4 processBatch(ms, stmt, parameters); 5 } 6 7 public void processBatch(MappedStatement ms, Statement stmt, List<Object> parameters) { 8 ResultSet rs = null; 9 try { 10 rs = stmt.getGeneratedKeys(); 11 final Configuration configuration = ms.getConfiguration(); 12 final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 13 final String[] keyProperties = ms.getKeyProperties(); 14 final ResultSetMetaData rsmd = rs.getMetaData(); 15 TypeHandler<?>[] typeHandlers = null; 16 if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) { 17 for (Object parameter : parameters) { 18 if (!rs.next()) break; // there should be one row for each statement (also one for each parameter) 19 final MetaObject metaParam = configuration.newMetaObject(parameter); 20 if (typeHandlers == null) typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties); 21 populateKeys(rs, metaParam, keyProperties, typeHandlers); //将生成的自增主键,可能是多个,设置到对象相对应的属性中 22 } 23 } 24 } catch (Exception e) { 25 throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e); 26 } finally { 27 if (rs != null) { 28 try { 29 rs.close(); 30 } catch (Exception e) { 31 // ignore 32 } 33 } 34 } 35 } 2.selectKeyGenerator 1 public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { 2 if (!executeBefore) { 3 processGeneratedKeys(executor, ms, parameter); 4 } 5 } 6 7 private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { 8 try { 9 if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) { 10 String[] keyProperties = keyStatement.getKeyProperties(); 11 final Configuration configuration = ms.getConfiguration(); 12 final MetaObject metaParam = configuration.newMetaObject(parameter); 13 if (keyProperties != null) { 14 // Do not close keyExecutor. 15 // The transaction will be closed by parent executor. 16 Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); 17 List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); //若是selectKey,则执行selectkey中的SQL语句查询,对于MySQL一般是select LAST_INSERT_ID() 18 if (values.size() == 0) { 19 throw new ExecutorException("SelectKey returned no data."); 20 } else if (values.size() > 1) { 21 throw new ExecutorException("SelectKey returned more than one value."); 22 } else { 23 MetaObject metaResult = configuration.newMetaObject(values.get(0)); 24 if (keyProperties.length == 1) { 25 if (metaResult.hasGetter(keyProperties[0])) { 26 setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0])); 27 } else { 28 // no getter for the property - maybe just a single value object 29 // so try that 30 setValue(metaParam, keyProperties[0], values.get(0)); 31 } 32 } else { 33 handleMultipleProperties(keyProperties, metaParam, metaResult); 34 } 35 } 36 } 37 } 38 } catch (ExecutorException e) { 39 throw e; 40 } catch (Exception e) { 41 throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e); 42 } 43 } (责任编辑:最模板) |