2010-05-12 23 views
7

Tôi đang sử dụng NamedParameterJdbcTemplate của Spring để thực hiện chèn vào bảng. Bảng sử dụng NEXTVAL trên một chuỗi để lấy khóa chính. Sau đó tôi muốn ID được tạo này được chuyển lại cho tôi. Tôi đang sử dụng thực hiện keyholder Spring như thế này:Sử dụng KeyHolder của Spring bằng các khóa chính được tạo bằng chương trình

KeyHolder key = new GeneratedKeyHolder(); 
jdbcTemplate.update(Constants.INSERT_ORDER_STATEMENT, params, key); 

Tuy nhiên, khi tôi chạy tuyên bố này, tôi nhận được:

org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number] 
    at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:73) 

Bất kỳ ý tưởng những gì tôi đang thiếu?

Trả lời

-3

Tôi nghĩ bạn đang sử dụng phương pháp sai trên JdbcTemplate. Là người duy nhất của update phương pháp mà dường như để phù hợp với đoạn mã của bạn là

int update(String sql, Object... args) 

Nếu vậy, bạn đang đi qua paramskey như một mảng hai yếu tố vargs, và JdbcTemplate được điều trị key như một ràng buộc thông thường các thông số và diễn dịch sai.

duy nhất phương pháp nào update trên JdbcTemplate mà phải mất một KeyHolder

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder) 

Vì vậy, bạn sẽ cần phải nói lại mã của bạn để sử dụng.

+2

gây hiểu nhầm, kiểm tra bên dưới câu trả lời của Konstantin –

2

Bạn phải thực thi JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k).

Khóa được trả về từ cơ sở dữ liệu sẽ được đưa vào đối tượng tham số KeyHolder.

Một ví dụ:

final String INSERT_ORDER_STATEMENT 
     = "insert into order (product_id, quantity) values(?, ?)"; 

KeyHolder keyHolder = new GeneratedKeyHolder(); 
    jdbcTemplate.update(new PreparedStatementCreator() { 
     public PreparedStatement createPreparedStatement(
      Connection connection) throws SQLException { 
       PreparedStatement ps = connection.prepareStatement(
        INSERT_ORDER_STATEMENT, new String[] { "id" }); 
       ps.setInt(1, order.getProductId()); 
       ps.setInt(2, order.getQuantity()); 
       return ps; 
      } 
     }, keyHolder); 

thông tin có thể tìm thêm here trong tài liệu tham khảo.

+0

Điều này thực sự trả về ROWID trong chủ sở hữu chứ không phải số! – supernova

15

Chỉ cần giải quyết một vấn đề tương tự - với Oracle bạn cần phải sử dụng một phương pháp khác (từ NamedParameterJdbcOperations) -

int update(String sql, 
      SqlParameterSource paramSource, 
      KeyHolder generatedKeyHolder, 
      String[] keyColumnNames) 
      throws DataAccessException 

với keyColumnNames chứa cột tự động tạo ra, trong trường hợp của tôi chỉ [ "Id"]. Nếu không, tất cả những gì bạn nhận được là ROWID. Xem Spring doc để biết chi tiết.

+1

Cảm ơn câu trả lời này câu hỏi tốt hơn câu trả lời trước và cũng giải quyết vấn đề của tôi –

+0

Không Oracle $ uck? Nhưng đây là câu trả lời đúng –

0

Không phức tạp về câu trả lời @konstantin: Đây là ví dụ hoàn chỉnh: Giả sử cơ sở dữ liệu là Oracle và tên cột lưu trữ Id được tạo là "GENERATED_ID" (Có thể là bất kỳ tên nào). LƯU Ý: Tôi đã sử dụng NamedParameterJdbcTemplate.update (....) Trong ví dụ này KHÔNG phải lớp JdbcTemplate của Spring.

 public Integer insertRecordReturnGeneratedId(final MyObject obj) 
      { 
      final String INSERT_QUERY = "INSERT INTO MY_TABLE VALUES(GENERATED_ID_SEQ.NEXTVAL, :param1, :param2)"; 
      try 
       { 
        MapSqlParameterSource parameters = new MapSqlParameterSource().addValue("param1", obj.getField1()).addValue("param2", obj.getField1()) ; 
        final KeyHolder holder = new GeneratedKeyHolder(); 
        this.namedParameterJdbcTemplate.update(INSERT_QUERY, parameters, holder, new String[] {"GENERATED_ID" }); 
        Number generatedId = holder.getKey(); 
        // Note: USING holder.getKey("GENERATED_ID") IS ok TOO. 
        return generatedId.intValue(); 
       } 
       catch(DataAccessException dataAccessException) 
       { 
     } 
     } 
Các vấn đề liên quan