插入前校验需求:如何避免CodeA与TitreA字段重复?
嘿,我来帮你搞定插入Album时避免CodeA和TitreA重复的问题!首先得提一句:你当前的代码直接把对象属性拼进SQL字符串里,存在SQL注入风险,这个我会在解决方案里一起优化掉,毕竟安全第一嘛。
下面给你两种靠谱的实现思路,你可以根据自己的需求选:
方案一:应用层先校验再插入(适合简单场景)
这种方式是在执行插入前,先查一遍数据库,确认没有重复的CodeA或TitreA(你可以根据实际需求调整是单个字段唯一,还是两个字段组合唯一)。
1. 先写一个校验重复的方法
public boolean isAlbumDuplicate(String codeA, String titreA) { // 用参数化查询,绝对不能拼字符串! String checkQuery = "SELECT COUNT(*) FROM album WHERE CodeA = ? OR TitreA = ?"; ResultSet rs = ConnexionMySQL.getInstance().executeQuery(checkQuery, codeA, titreA); try { if (rs.next()) { // 只要计数大于0,说明已有重复记录 return rs.getInt(1) > 0; } } catch (SQLException e) { e.printStackTrace(); } finally { // 别忘了关闭ResultSet,根据你的工具类实现调整 try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return false; }
2. 修改你的插入方法,加入校验逻辑
public boolean insertAlbum(Album alb) { // 先校验:如果重复直接返回false if (isAlbumDuplicate(alb.getCodeA(), alb.getTitreA())) { System.out.println("警告:该CodeA或TitreA已经存在,无法插入!"); return false; } // 换成参数化SQL,彻底杜绝SQL注入 String insertSql = "INSERT INTO album (CodeA, TitreA, SortieA, IdentC) VALUES (?, ?, ?, ?)"; boolean insertSuccess = ConnexionMySQL.getInstance().actionQuery( insertSql, alb.getCodeA(), alb.getTitreA(), alb.getSortieASQL(), alb.getChanteurAlb().getIdentC() ); return insertSuccess; }
方案二:数据库层面加唯一约束(更可靠,解决并发问题)
应用层校验有个小问题:如果两个请求同时插入相同数据,可能会因为校验和插入之间的时间差,导致重复数据漏进来。所以更稳妥的方式是让数据库帮我们兜底,加唯一约束。
1. 给表加唯一约束
如果你要保证CodeA唯一,执行这条SQL:
ALTER TABLE album ADD CONSTRAINT uk_album_codeA UNIQUE (CodeA);
如果是CodeA和TitreA组合起来唯一(比如同一歌手下标题不能重复?),就用这条:
ALTER TABLE album ADD CONSTRAINT uk_album_codeA_titreA UNIQUE (CodeA, TitreA);
2. 修改插入方法处理约束冲突
加了约束后,插入重复数据时数据库会抛出异常,我们在代码里捕获这个异常就行:
public boolean insertAlbum(Album alb) { try { String insertSql = "INSERT INTO album (CodeA, TitreA, SortieA, IdentC) VALUES (?, ?, ?, ?)"; return ConnexionMySQL.getInstance().actionQuery( insertSql, alb.getCodeA(), alb.getTitreA(), alb.getSortieASQL(), alb.getChanteurAlb().getIdentC() ); } catch (SQLException e) { // MySQL里唯一约束冲突的错误码是1062,其他数据库可能不一样,注意调整 if (e.getErrorCode() == 1062) { System.out.println("该CodeA或TitreA已存在,插入失败!"); return false; } // 其他异常正常处理 e.printStackTrace(); return false; } }
关键提醒:一定要用参数化查询!
你原来的代码直接拼接字符串到SQL里,真的非常危险——比如如果有人把alb.getCodeA()的值设为'); DROP TABLE album; --,你的整张表都会被删掉!所以不管用哪种方案,都要换成参数化查询,上面的代码已经帮你改好了,确保你的ConnexionMySQL工具类支持这种参数化调用(如果原来的actionQuery不支持,你需要修改它,用PreparedStatement来实现)。
内容的提问来源于stack exchange,提问作者julliiie
相关产品推荐
相关产品推荐

