批量插入MariaDB成功但ReturnGeneratedKeys返回空值的问题求助
解决MariaDB批处理插入后无法获取生成键的问题
看起来你遇到的问题是批处理插入成功,但无法通过getGeneratedKeys()获取自增主键,这在使用MariaDB JDBC驱动配合executeBatch()时确实容易出现,尤其是和autoCommit的设置有关。我来帮你分析原因并给出修复方案:
核心问题分析
当autoCommit设为true时,执行executeBatch()后连接会自动提交事务,这时候JDBC驱动可能已经释放了与生成键相关的资源,导致后续调用getGeneratedKeys()返回空的结果集。虽然你说设为false时数据插不进去,但那是因为你没有手动提交事务——只要调整流程,关闭autoCommit并手动提交,就能同时解决数据插入和生成键获取的问题。
另外,我注意到你的代码里有个小笔误:ps2.setShort(7, equip.getProperty("INT"));这里重复设置了INT,应该是LUK,这个也需要修正,避免数据错误。
修复后的代码
try (Connection con = DatabaseConnection.getConnection()) { // 关闭自动提交,手动控制事务 con.setAutoCommit(false); try (PreparedStatement ps = con.prepareStatement( "INSERT INTO items (chrid, accountid, type, pos, itemid) VALUES (?,?,?,?,?)", Statement.RETURN_GENERATED_KEYS)) { ArrayList<Pair<Integer, Equip>> equips = new ArrayList<>(); for (Pair<Integer, Integer> item : items) { equips.add(itemCreationSystem.createEquip(item.right)); ps.setInt(1, dbId.dbId); ps.setInt(2, client.accountId); ps.setInt(3, 0); ps.setInt(4, item.left); ps.setInt(5, item.right); ps.addBatch(); } // 执行第一个批处理 ps.executeBatch(); // 获取生成的主键 try (ResultSet rs = ps.getGeneratedKeys()) { try (PreparedStatement ps2 = con.prepareStatement( "INSERT INTO equips (itemKey, slots, successfulUpgrades, str, dex, intel, luk, hp, mp, " + "wAtk, mAtk, wDef, mDef, equipPos)")) { while (rs.next()) { Pair<Integer, Equip> pair = equips.remove(0); Equip equip = pair.right; ps2.setInt(1, rs.getInt(1)); ps2.setShort(2, equip.upgradeSlots); ps2.setShort(3, equip.successfulUpgrades); ps2.setShort(4, equip.getProperty("STR")); ps2.setShort(5, equip.getProperty("DEX")); ps2.setShort(6, equip.getProperty("INT")); // 修正:把重复的INT改成LUK ps2.setShort(7, equip.getProperty("LUK")); ps2.setShort(8, equip.getProperty("HP")); // 注意:原代码写的是MMP,需确认数据库字段是mp还是mmp,避免字段不匹配 ps2.setShort(9, equip.getProperty("MP")); ps2.setShort(10, equip.getProperty("PAD")); ps2.setShort(11, equip.getProperty("MAD")); ps2.setShort(12, equip.getProperty("PDD")); ps2.setShort(13, equip.getProperty("MDD")); ps2.setInt(14, pair.left); ps2.addBatch(); } // 执行第二个批处理 ps2.executeBatch(); } } // 所有操作完成后,手动提交事务 con.commit(); } catch (SQLException e) { // 出错时回滚事务,保证数据一致性 con.rollback(); e.printStackTrace(); } } catch (SQLException e) { e.printStackTrace(); }
关键调整点
- 关闭
autoCommit:将连接的自动提交设为false,让所有操作处于同一个事务中,避免提前释放生成键相关的资源。 - 手动提交事务:在所有批处理执行完成且无错误后,调用
con.commit()提交数据,确保数据成功插入。 - 事务回滚:如果任何步骤抛出异常,调用
con.rollback()回滚所有操作,防止出现部分插入的不一致情况。 - 修正字段赋值错误:修复了重复设置
INT的问题,同时核对了MP字段的赋值(原代码写的MMP需和数据库字段名对应)。
额外建议
- 确保你使用的是最新版本的MariaDB JDBC驱动(Connector/J 3.0.0+),旧版本对批处理生成键的支持可能不完善。
- 确认
items表的主键是自增字段(比如itemKey INT AUTO_INCREMENT PRIMARY KEY),这是RETURN_GENERATED_KEYS生效的前提。
内容的提问来源于stack exchange,提问作者Jon Nguyen
相关产品推荐
相关产品推荐

