插入前检查注册数据? JAVA

时间:2015-12-08 01:24:23

标签: java mysql database

我在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)

3 个答案:

答案 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的行,则下面的建议解决方案可能仍然容易出错。要解决此问题,您可以:

    插入

    之前
  • Lock tables

  • 或者,如果您不关心哪个插页获胜,您可以INSERT IGNORE。使用INSERT IGNORE

  • 时,MySQL不会返回重复键错误的错误(或警告)
  • 最后,您可以使用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注入的更多信息:

https://en.wikipedia.org/wiki/SQL_injection

What is SQL injection?

https://stackoverflow.com/search?q=sql+injection