指定周可用游戏全量入库异常:代码仅插入6条数据的排查
问题排查:指定周游戏存入数据库仅插入6条数据的原因
需求
编写代码将指定周(weekNumber)的所有可用游戏存入数据库。
提供的代码
public static void main(String[] args) { try { Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/nflpickem", "root", "root"); System.out.println("Create USER/GAME (bases)"); String[] users = {"red", "blue"}; String[] grps = {"bronze", "gold", "silver"}; int gameID = 10000; int pid = 10000; int weekNumber = 1; for (int i = 0; i < users.length; i++) { for (int y = 0; y < grps.length; y++) { //modified the loop condition for 'grps' to avoid index out of bounds String sql = "INSERT INTO PICKS VALUES ("; sql = sql + ++pid + ","; sql = sql + "'" + users[i] + "',"; sql = sql + "'" + grps[y] + "',"; sql = sql + "" + ++gameID + ","; sql = sql + "" + weekNumber + ","; if (i < users.length/2) { // add all picks for half of the users sql = sql + "'ATL')"; } else if (i == 1 && y == 1) { // add some picks for specific user sql = sql + "'BUF')"; } else { // add no picks for users sql = sql + "'NO')"; } System.out.println(sql); try { conn.createStatement().execute(sql); } catch (Exception e) { System.out.println(e.getMessage()); } } } System.out.println("Table USER created!"); } catch (Exception e) { System.out.println("oops:" + e); } }
问题现象
运行代码后仅存入6条数据,无论该周可用游戏数量多少,始终只能插入6条。
已尝试方案
- 调整周与gameID关联
- 拆分查询
- 用HashSet存储gameID
- 强制关联week1数据
以上方案均未解决,求助排查原因。
原因分析
问题根源非常直接:当前代码完全没有和指定周的可用游戏数据产生关联。代码里的循环是基于固定的users数组(长度2)和grps数组(长度3)做嵌套遍历,2*3=6次循环,每次循环插入1条数据,所以必然只会生成6条记录。
代码里的gameID是手动自增的固定值,不是从数据库或其他数据源获取的该周实际可用游戏ID,自然不会根据周内游戏数量动态生成数据。
修复思路及示例代码
- 先查询指定周的所有可用游戏ID列表
- 遍历用户、分组、游戏的笛卡尔积,为每个组合插入记录
- 使用
PreparedStatement避免SQL注入,同时提升执行效率 - 注意资源的关闭,防止连接泄漏
修改后的示例代码:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; public class GamePicker { public static void main(String[] args) { Connection conn = null; PreparedStatement insertStmt = null; PreparedStatement gameQueryStmt = null; ResultSet rs = null; try { // 1. 建立数据库连接 conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/nflpickem", "root", "root"); System.out.println("连接数据库成功"); int weekNumber = 1; String[] users = {"red", "blue"}; String[] grps = {"bronze", "gold", "silver"}; int pid = 10000; // 2. 查询指定周的所有可用游戏ID List<Integer> gameIds = new ArrayList<>(); String gameSql = "SELECT game_id FROM games WHERE week_number = ?"; gameQueryStmt = conn.prepareStatement(gameSql); gameQueryStmt.setInt(1, weekNumber); rs = gameQueryStmt.executeQuery(); while (rs.next()) { gameIds.add(rs.getInt("game_id")); } if (gameIds.isEmpty()) { System.out.println("该周没有可用游戏"); return; } // 3. 准备插入语句(使用PreparedStatement防止SQL注入) String insertSql = "INSERT INTO PICKS (pid, user, grp, game_id, week_number, pick) VALUES (?, ?, ?, ?, ?, ?)"; insertStmt = conn.prepareStatement(insertSql); // 4. 遍历用户、分组、游戏,插入所有组合 for (String user : users) { for (String grp : grps) { for (int gameId : gameIds) { // 设置参数 insertStmt.setInt(1, ++pid); insertStmt.setString(2, user); insertStmt.setString(3, grp); insertStmt.setInt(4, gameId); insertStmt.setInt(5, weekNumber); // 根据用户设置pick值,保留原逻辑 if (user.equals("red")) { insertStmt.setString(6, "ATL"); } else if (user.equals("blue") && grp.equals("gold")) { insertStmt.setString(6, "BUF"); } else { insertStmt.setString(6, "NO"); } // 添加到批处理(可选,提升效率) insertStmt.addBatch(); } } } // 执行批处理插入 insertStmt.executeBatch(); System.out.println("成功插入 " + (users.length * grps.length * gameIds.size()) + " 条数据"); } catch (Exception e) { e.printStackTrace(); } finally { // 5. 关闭资源 try { if (rs != null) rs.close(); if (gameQueryStmt != null) gameQueryStmt.close(); if (insertStmt != null) insertStmt.close(); if (conn != null) conn.close(); } catch (Exception e) { e.printStackTrace(); } } } }
说明
- 假设存储周游戏的表名为
games,包含game_id和week_number字段,你需要根据实际表结构调整查询语句 - 使用
PreparedStatement替代字符串拼接SQL,避免SQL注入风险,同时重复利用语句提升性能 - 加入了资源关闭逻辑,防止数据库连接泄漏
- 插入逻辑改为基于实际查询到的游戏ID列表,数据量会随周内游戏数量动态变化
内容的提问来源于stack exchange,提问作者Bananazoid
相关产品推荐
相关产品推荐

