Câu lệnh chuẩn bị với câu lệnh.RETURN_GENERATED_KEYS


83

Cách duy nhất mà một số trình điều khiển JDBC trả lại Statement.RETURN_GENERATED_KEYSlà thực hiện một số điều sau đây:

long key = -1L;
Statement statement = connection.createStatement();
statement.executeUpdate(YOUR_SQL_HERE, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = statement.getGeneratedKeys();
if (rs != null && rs.next()) {
    key = rs.getLong(1);
}

Có cách nào để làm điều tương tự với PreparedStatement?


Biên tập

Lý do tôi hỏi liệu tôi có thể làm điều tương tự khi PreparedStatementxem xét tình huống sau:

private static final String SQL_CREATE = 
            "INSERT INTO
            USER(FIRST_NAME, MIDDLE_NAME, LAST_NAME, EMAIL_ADDRESS, DOB) 
            VALUES (?, ?, ?, ?, ?)";

Trong USERbảng có một PRIMARY KEY (USER_ID)là a BIGINT AUTOINCREMENT(do đó tại sao bạn không thấy nó trong SQL_CREATEChuỗi.

Bây giờ, tôi điền việc ?sử dụng PreparedStatement.setXXXX(index, value). Tôi muốn trở về ResultSet rs = PreparedStatement.getGeneratedKeys(). Làm thế nào tôi có thể đạt được điều này?


2
Nhiều người hiểu sai và sử dụng PreparedStatement # executeUpdate (arg). Java doc cho biết This method with argument cannot be called on a PreparedStatement or CallableStatement.Điều đó có nghĩa là chúng ta phải sử dụng executeUpdate () mà không có đối số mặc dù executeUpdate(arg)phương thức có thể được kế thừa trong lớp PreparedStatement nhưng chúng ta không cần phải sử dụng nó nếu không sẽ nhận được SQLException.
AmitG

Câu trả lời:


141

Bạn có thể sử dụng prepareStatementphương pháp lấy một inttham số bổ sung

PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)

Đối với một số trình điều khiển JDBC (ví dụ: Oracle), bạn phải liệt kê rõ ràng tên cột hoặc chỉ số của các khóa được tạo:

PreparedStatement ps = con.prepareStatement(sql, new String[]{"USER_ID"})

Tôi đã chấp nhận câu trả lời của bạn vì bạn đã chỉ ra nhiều cách hơn để đạt được kết quả tương tự.
Buhake Sindi

67

Ý bạn là một cái gì đó như thế này?

long key = -1L;

PreparedStatement preparedStatement = connection.prepareStatement(YOUR_SQL_HERE, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.setXXX(index, VALUE);
preparedStatement.executeUpdate();

ResultSet rs = preparedStatement.getGeneratedKeys();

if (rs.next()) {
    key = rs.getLong(1);
}

Làm cách nào để tập kết quả khóa được tạo có thể là rỗng?
AlikElzin-kilaka

10

Hiện tôi không có trình biên dịch, tôi sẽ trả lời bằng cách đặt một câu hỏi:

Bạn đã thử cái này chưa? Nó có hoạt động không?

long key = -1L;
PreparedStatement statement = connection.prepareStatement();
statement.executeUpdate(YOUR_SQL_HERE, PreparedStatement.RETURN_GENERATED_KEYS);
ResultSet rs = statement.getGeneratedKeys();
if (rs != null && rs.next()) {
    key = rs.getLong(1);
}

Tuyên bố từ chối trách nhiệm: Rõ ràng là tôi chưa biên soạn cái này, nhưng bạn có thể hiểu được.

PreparedStatement là một giao diện con của Statement , vì vậy tôi không hiểu lý do tại sao điều này không hoạt động, trừ khi một số trình điều khiển JDBC bị lỗi.


đó không phải là những gì tôi đang tìm kiếm Tôi biết rằng đó PreparedStatementlà một lớp con của Statement.... xem bài đăng cập nhật của tôi.
Buhake Sindi

2
String query = "INSERT INTO ....";
PreparedStatement preparedStatement = connection.prepareStatement(query, PreparedStatement.RETURN_GENERATED_KEYS);

preparedStatement.setXXX(1, VALUE); 
preparedStatement.setXXX(2, VALUE); 
....
preparedStatement.executeUpdate();  

ResultSet rs = preparedStatement.getGeneratedKeys();  
int key = rs.next() ? rs.getInt(1) : 0;

if(key!=0){
    System.out.println("Generated key="+key);
}

Nếu khóa được tạo ra sau đó chủ chốt khác key = 0 nếu không được tạo ra
Dharmendrasinh Chudasama

0
private void alarmEventInsert(DriveDetail driveDetail, String vehicleRegNo, int organizationId) {

    final String ALARM_EVENT_INS_SQL = "INSERT INTO alarm_event (event_code,param1,param2,org_id,created_time) VALUES (?,?,?,?,?)";
    CachedConnection conn = JDatabaseManager.getConnection();
    PreparedStatement ps = null;
    ResultSet generatedKeys = null;
    try {
        ps = conn.prepareStatement(ALARM_EVENT_INS_SQL, ps.RETURN_GENERATED_KEYS);
        ps.setInt(1, driveDetail.getEventCode());
        ps.setString(2, vehicleRegNo);
        ps.setString(3, null);
        ps.setInt(4, organizationId);
        ps.setString(5, driveDetail.getCreateTime());
        ps.execute();
        generatedKeys = ps.getGeneratedKeys();
        if (generatedKeys.next()) {
            driveDetail.setStopDuration(generatedKeys.getInt(1));
        }
    } catch (SQLException e) {
        e.printStackTrace();
        logger.error("Error inserting into alarm_event : {}", e
                .getMessage());
        logger.info(ps.toString());
    } finally {
        if (ps != null) {
            try {

                if (ps != null)
                    ps.close();
            } catch (SQLException e) {
                logger.error("Error closing prepared statements : {}", e
                        .getMessage());
            }
        }
    }
    JDatabaseManager.freeConnection(conn);
}

1
Bạn không nên giải phóng kết nối của mình trong khối cuối cùng, chứ không phải bên ngoài nó (bạn sẽ mất kết nối nếu gặp bất kỳ loại ngoại lệ thời gian chạy nào)?
Jules

@niraj - thay vì ps.RETURN_GENERATED_KEYS, chúng ta có thể viết Statement.RETURN_GENERATED_KEYS vì nó là biến tĩnh trong lớp java.sql.Statement.
AmitG
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.