2013-04-20 34 views
6

Dưới đây là đoạn code mà hoạt động:Lấy id nối tiếp từ hàng loạt lắp vào postgresql

 Connection c = ds.getConnection(); 
     c.setAutoCommit(false); 
     PreparedStatement stmt = c.prepareStatement("INSERT INTO items (name, description) VALUES(?, ?)"); 
     while (!(items = bus.take()).isEmpty()) { 
      for (Item item : items) { 
      stmt.setString(1, item.name); 
      stmt.setString(2, item.description); 
      stmt.addBatch(); 
      } 
      stmt.executeBatch(); 
      c.commit(); 
     } 

Nhưng bây giờ tôi cần phải cư khác bàn nơi id là khóa ngoại. Nếu tôi sử dụng INSERT với RETURNING id thì executeBatch không thành công với lỗi "Kết quả đã được trả về khi không ai được mong đợi".

tôi thấy một số cách để giải quyết việc này

  • Do chèn cá nhân chứ không phải là chèn hàng loạt.
  • Thay thế id nối tiếp bằng guid được tạo bởi khách hàng.
  • Sử dụng một số loại thủ tục được lưu trữ để thực hiện chèn hàng loạt và trả về danh sách các id.

Trong ba phương pháp mà tôi thấy cái cuối cùng dường như bảo toàn cả hiệu quả chèn hàng loạt và trả lại id, nhưng nó cũng phức tạp nhất đối với tôi vì tôi chưa bao giờ viết thủ tục lưu trữ.

Có cách nào tốt hơn để chèn hàng loạt và nhận ID không? Tôi không có vấn đề bằng cách sử dụng API cụ thể postgresql thay vì jdbc.

Nếu không, bất kỳ ai có thể phác thảo quy trình được lưu trữ này không?

Dưới đây là lược đồ bảng:

CREATE UNLOGGED TABLE items 
(
    id serial, 
    name character varying(1000), 
    description character varying(10000) 
) 
WITH (
    OIDS=FALSE 
); 
+0

Hãy xem phương pháp JDBC 'getGeneratedKeys'. Tôi đã không xác minh cụ thể nó cho các kết nối hàng loạt, mặc dù. –

+0

Làm thế nào về populating cả hai bảng cùng một lúc với wCTE? –

+0

@JakubKania - wCTE là gì? Bạn có thể cho thấy một ví dụ? – mark

Trả lời

10

Something như thế này nên làm việc:

// tell the driver you want the generated keys 
stmt = c.prepareStatement("INSERT ... ", Statement.RETURN_GENERATED_KEYS); 

stmt.executeBatch(); 

// now retrieve the generated keys 
ResultSet rs = stmt.getGeneratedKeys(); 
while (rs.next()) { 
int id = rs.getInt(1); 
.. save the id somewhere or update the items list 
} 

Tôi nghĩ (! Tôi không chắc chắn) mà các phím được trả về theo thứ tự chúng đã được tạo. Vì vậy, hàng đầu tiên từ ResultSet sẽ ánh xạ tới "mục" đầu tiên từ danh sách bạn đang xử lý. Nhưng hãy xác minh điều đó!

Sửa

Nếu điều đó không làm việc, cố gắng xác định các cột thực tế mà các giá trị được tạo ra:

stmt = c.prepareStatement("INSERT ... ", new String[] {"id"}); 
+0

Điều đó không có tác dụng - tập kết quả trả về trống. – mark

+0

@mark: bạn cần báo cho người lái xe trả lại các giá trị đó khi bạn chuẩn bị bản sao kê. Xem chỉnh sửa của tôi. –

+1

OK, hoạt động. Nhưng một cái gì đó còn lại. Bạn âm thanh không chắc chắn liệu hàng đầu tiên bản đồ đến id trả về đầu tiên. Tài liệu tại http://docs.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/preparedstatement.html cũng không nói gì về điều này. Tuy nhiên, đây là một phần thông tin quan trọng. Nếu không có điều này đảm bảo tính năng này là vô ích. Nó được đảm bảo, ít nhất là cho postgresql? – mark

Các vấn đề liên quan