我在SQL中有一个数据库,其中有一个名为“Vehicle”的表。它有一个主键作为VARCHAR。我正在试图做的是验证我输入的ID是否已经注册。 “盘子”是我的主键。
这是我在Vehicle类上的“插入”方法:
int match = 0;
try {
String query = "insert into vehicle values ('"+this.plate+"','"+this.maker+"','"+this.model+"','"+this.color+"','"+this.year+"','"+ this.price+"') ";
state = con.createStatement();
match = state.executeUpdate(query);
return match;
} catch (SQLException ex) {
Logger.getLogger(Vehicle.class.getName()).log(Level.SEVERE, null, ex);
}
return match;
这是我在内部框架上的“插入”代码:
String plate = txtPlate.getText().trim();
String model = txtModel.getText().trim();
String maker = txtMker.getText().trim();
String color = txtColor.getText().trim();
String year = txtYear.getText().trim();
String price = txtPrice.getText().trim();
if(plate.equals("") || maker.equals("") || model.equals("") || color.equals("") || year.equals("") || price.equals("") )
JOptionPane.showMessageDialog(rootPane, "Cant leave blank spaces");
else{
try {
int year = Integer.parseInt(year);
int price = Integer.parseInt(price);
Vehicle v1 = new Vehicle(plate, model, maker, color, year, price);
if (v1.insert() > 0)
{
JOptionPane.showMessageDialog(rootPane, "Register succes!");
}else
{
JOptionPane.showMessageDialog(rootPane, "Register failed");
}
}catch (NumberFormatException exc)
{
JOptionPane.showMessageDialog(this, "Error, insert numbers on 'YEAR and PRICE'");
}
}
我尝试捕获异常,但没有奏效。每次我添加一个重复的Plate(PK)时,我的程序会引发异常,但我似乎无法使用它。
尝试添加具有相同印版(PK)的车辆后,这是一些日志
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'ARP22' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
答案 0 :(得分:1)
使用INSERT IGNORE(特定于MySQL),或使用SQLException作为重复键的信号。 INSERT IGNORE不会抛出异常。
最好还是使用PreparedStatement。除了作为针对SQL注入的安全措施之外,它还可以像撇号和反斜杠一样逃避特殊字符。并允许类型。
String query = "insert ignore into"
+ " vehicle(plate, maker, model, color, year, price)"
+ " values(?, ?, ?, ?, ?, ?)";
try (PreparedStatement stm = con.prepareStatement(query)) {
stm.setString(1, this.plate);
stm.setString(2, this.maker);
stm.setString(3, this.model);
stm.setString(4, this.color);
stm.setInt(5, this.year);
stm.setInt(6, this.price);
match = state.executeUpdate();
}
列出列名可确保数据库更改保持可跟踪状态。
答案 1 :(得分:0)
你基本上有两种选择。
第一个选项是通过执行SELECT
来检查数据库中是否已存在主键(PK)。如果它存在,那么UPDATE
行,如果不是INSERT
新行。
第二个选项是使用INSERT ON DUPLICATE KEY UPDATE
。这将自动检测PK何时存在,并在需要时执行UPDATE
。如果我猜表列名称,它可能看起来像:
String query = "insert into vehicle values ('"+this.plate+"','"+this.maker+"','"+this.model+"','"+this.color+"','"+this.year+"','"+ this.price+"') "+
"on duplicate key update vehicle.maker = values(maker), vehicle.model = values(model), vehicle.color = values(color), vehicle.year = values(year), vehicle.price = values(price) ";
旁注:
答案 2 :(得分:0)
插入
的竞争条件更新正如@david指出的那样,如果第二个源尝试插入与您当前尝试插入的行具有相同PK的行,则下面的建议解决方案可能仍然容易出错。要解决此问题,您可以:
或者,如果您不关心哪个插页获胜,您可以INSERT IGNORE。使用INSERT IGNORE
最后,您可以使用INSERT ... ON DUPLICATE KEY UPDATE。如果PK不存在,这将插入行,否则它将更新现有的行。
要在插入数据库时防止异常,只需在尝试插入之前查询将插入的板号:
select 1 from vehicle where plate = <vehicle_plate>
如果从该查询返回任何内容,则您知道车辆ID已存在。上面的查询假设plate
是该字段是车辆的PK。
然而,更重要的是,与数据库交互的代码容易受到SQL注入的攻击。</ strong>
将查询字符串中的用户输入传递给数据库永远是个好主意。请使用parameterized queries。其他链接:parameterized queries in Java。
有关SQL注入的更多信息: