JDBC insert 返回自增主键原理

插入是返回自增 id 这个功能在 jdbc 上就已经实现了,所以 mybatis 只是对其进行了封装,先研究 jdbc 返回自增主键得原理。

以下是部分 jdbc 代码

 PreparedStatement pst = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
​
        // 执行SQL
        pst.setString(1, "qqqq");
        pst.setInt(2, 15);
        int count = pst.executeUpdate();
​
        // 获取主键值
        ResultSet rs = pst.getGeneratedKeys();

首先可以看到,在进行预处理得时候,就通过 Statement.RETURN_GENERATED_KEYS 来设置这次会话可以拿到自增主键。

@Override
    public java.sql.PreparedStatement prepareStatement(String sql, int autoGenKeyIndex) throws SQLException {
        java.sql.PreparedStatement pStmt = prepareStatement(sql);
​
        ((ClientPreparedStatement) pStmt).setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS);
​
        return pStmt;
    }
​
// 将 retrieveGeneratedKeys 设置为 true
 protected void setRetrieveGeneratedKeys(boolean flag) throws SQLException {
        synchronized (checkClosed().getConnectionMutex()) {
            this.retrieveGeneratedKeys = flag;
        }
    }

执行完 sql 后我们看 getGeneratedKeys() 是怎么拿到主键得。

 @Override
    public java.sql.ResultSet getGeneratedKeys() throws SQLException {
        // 还记得 retrieveGeneratedKeys 这个变量吗,加入没有设置可以拿到自增主键就直接抛出异常。
      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();
            }
.....
        }
    }

接着点下去会发现,只是通过 long beginAt = getLastInsertID(); 这行代码拿到了新增后最后的那个 id ,但是只是拿到了一个属性,那么这个 lastInsertId 属性是怎么设置进去得呢,那么就需要看

jdbc 代码中的 pst.executeUpdate(),来看看到 sql 是如何执行的。

protected long executeUpdateInternal(QueryBindings bindings, boolean isReallyBatch) throws SQLException {
    ....
    rs = executeInternal(-1, sendPacket, false, false, null, isReallyBatch);
    ....
    this.lastInsertId = rs.getUpdateID();
    .....
}

能发现当真正执行完之后,是通过结果集的 UpdateID 来给 lastInsertId 来赋值的。当我想怎么才能查看到 updateId 是什么时候被赋值的时候。我发现后面的源码基本与是否开启自增主键无关,而是不管是否开启返回自增主键,每次执行完之后,updateId 都会是插入后的最新值。

结论

开启不管是否要求 jdbc 返回主键值,其实它每次插入后都会拿到这个值。MyBatis 也是同理,只是解析了 xml 文件,通过是否设置 useGeneratedKeys 来设置相应的连接,另外 MyBatis 可以通过 keyProperty 里面的主键名来自动帮我们进行映射。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值