如何在 Java servlet 中处理多个请求

How to handle multiple request in Java servlet

我有一个 UI,其中 HTML table 的输入字段作为单元格,一些输入字段在 HTML table 之外,所以有我正在输入数据,然后使用 servlets

将保存数据保存到我的数据库中

一次只有一个用户使用它时工作正常,但当两个用户同时单击保存时会出现问题

我做的是:

我面临的问题是:

我的代码

int grnNo;
Connection con = null;
Statement statement = null;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    String[] itemCode = request.getParameterValues("itemCodetd");
    String[] unitCode = request.getParameterValues("unittd");

    try {
        con = DBConnection.createConnection();
        statement = con.createStatement();

        String grnNoSql = "select max(GRNNUMBER)+1 as GRNNo from egoodsreceived";
        ResultSet resultSet1 = statement.executeQuery(grnNoSql);

        while (resultSet1.next()) {
            int grnNoLocal = resultSet1.getInt("GRNNo");

            if (grnNo != 0) {
                grnNo = grnNoLocal;
                System.out.println("in if  :" + grnNo);
            } else {
                grnNo = 1;
                System.out.println("in else  :" + grnNo);
            }

        }

        String query1 = "query to insert data";

        PreparedStatement ps = con.prepareStatement(query1);

        for (int i = 0; i < itemCode.length; i++) {
            if (itemCode[i] != "") {
                System.out.println("in for :" + grnNo);
                ps.setInt(1, grnNo);
                ps.setString(2, itemCode[i]);
                ps.setString(3, unitCode[i]);

                ps.addBatch();
            }
        }

        ps.executeBatch(); // here getting erro as duplicate primary key

    } catch (SQLException e) {
        System.out.println("SQL EXCPTION   91");
        e.printStackTrace();
    }

    doGet(request, response);
}

问题是您在 servlet 中使用了实例变量。 JVM 中每个 servlet 只有一个实例,因此并发请求将尝试同时使用同一个变量。

grnNoconstatement 重构为局部变量,然后包装 select 并插入到单个事务中。

您应该定义要使用 MySQL 的自动递增功能的列:

https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html

CREATE TABLE X(
     id MEDIUMINT NOT NULL AUTO_INCREMENT,
     PRIMARY KEY (id)
);

然后您不需要在插入语句中指定列或其值:该值将由数据库自动分配。

另一个答案提出了关于 Servlet 中实例变量的线程安全的有效观点,但是,在不添加同步块的情况下,使grnNo局部变量无法解决问题:

//Thread T1 executes the below and get the next val
//before T1 has written its changes, T2 executes the below and gets the next val
String grnNoSql = "select max(GRNNUMBER)+1 as GRNNo from egoodsreceived";

如果你需要在应用程序中插入后生成的标识符,那么你可以使用java.sql.statement的getGeneratedKeys()方法:

https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#getGeneratedKeys()