2009-08-27 44 views
17

Khi sử dụng một trong các phương thức mẫu JDBC khác nhau, tôi bị nhầm lẫn về cách lặp/cuộn qua tập kết quả lớn (không phù hợp với bộ nhớ). Ngay cả khi không có một tiếp xúc trực tiếp của một giao diện Iterable tôi ít nhất sẽ mong đợi trường hợp của RowCallbackHandler để có được gọi là trong khi truy vấn được thực hiện không sau khi nó kết thúc (hoặc overfloats đống).Hỗ trợ Spring JDBC và tập dữ liệu lớn

Tôi đã xem qua số this (không thay đổi gì đối với tôi mặc dù tương tự về tinh thần với this post khi tràn ngăn xếp) và tại this đăng trong diễn đàn mùa xuân. Sau này dường như gợi ý rằng trình xử lý gọi lại thực sự nên được gọi trong khi con trỏ đang tìm nạp dữ liệu. Tuy nhiên, các thử nghiệm của tôi cho thấy không có hành vi như vậy.

Cơ sở dữ liệu là một Oracle10g. Tôi đang sử dụng trình điều khiển sản xuất 11.1.0.7.0 và Spring 2.5.6.SEC01. Bất kỳ ý tưởng bất cứ ai làm thế nào để lặp qua bộ kết quả, tốt nhất là trong khi giữ logic lập bản đồ của RowMapper vv?

Trả lời

19

Trình điều khiển JDBC Oracle có hỗ trợ thích hợp cho phương pháp setFetchSize() trên java.sql.Statement, cho phép bạn kiểm soát số lượng hàng mà trình điều khiển sẽ tìm nạp trong một lần.

Tuy nhiên, RowMapper do Spring sử dụng bằng cách đọc từng hàng vào bộ nhớ, nhận RowMapper để dịch thành đối tượng và lưu trữ đối tượng của mỗi hàng trong một danh sách lớn. Nếu tập hợp kết quả của bạn là rất lớn, thì danh sách này sẽ lớn, bất kể JDBC lấy dữ liệu hàng như thế nào.

Nếu bạn cần xử lý các tập hợp kết quả lớn, thì RowMapper không thể mở rộng được. Bạn có thể cân nhắc sử dụng RowCallbackHandler thay vào đó, cùng với các phương thức tương ứng trên JdbcTemplate. RowCallbackHandler không ra lệnh kết quả được lưu trữ như thế nào, để bạn lưu trữ chúng.

+1

setFetchSize không thay đổi mọi thứ đối với tôi, tôi đã thử sử dụng nó trước đây. Bạn có phát triển chống lại một cá thể Oracle không? Đối với tôi RowCallBackHandler chỉ bị treo, chờ truy vấn kết thúc như tôi đã viết trong OP của tôi. – yawn

+2

Rõ ràng tôi đã quên cuộc gọi afterPropertiesSet() trên mẫu JDBC trong bài kiểm tra của tôi. Xấu hổ, nhưng bây giờ nó hoạt động: *) – yawn

4

Đó là tài sản của trình điều khiển/kết nối xem có truyền lại dữ liệu cho bạn hay không hoặc gửi lại dữ liệu đó trong một đoạn. Ví dụ, trong SQL Server, bạn sử dụng SelectMethod tài sản trên URL kết nối:

jdbc:microsoft:sqlserver://gsasql03:1433;DatabaseName=my_db;SelectMethod=direct

Giá trị của direct có nghĩa là kết quả nên đến trong một đi. Lựa chọn khác là cursor, cho phép bạn chỉ định rằng bạn muốn kết nối truyền trực tuyến kết quả cho bạn. Tôi không chắc tương tự của nguồn dữ liệu Oracle là gì, tôi sợ

RowCallbackHandler chắc chắn có tác dụng đối với tôi.

+0

Vâng, lý tưởng bạn không đưa vào một tập dữ liệu, bạn sẽ lấy các hồ sơ trong khi keepin kết nối chào bán công khai nếu có nhiều hồ sơ. Tôi đã làm điều này trong .NET và có một cải thiện khá tốt về hiệu suất. Tôi tưởng tượng một cái gì đó tương tự cho java sẽ tồn tại, đặc biệt là vào mùa xuân. – Zoidberg

+0

@ * Zoidberg * - OP dường như đang hoạt động chính xác, sử dụng trình xử lý gọi lại hàng –

+0

Điều này nghe có vẻ đầy hứa hẹn. Thật không may tôi không thể tìm thấy bất cứ điều gì tương tự như thiết lập URL SQL Server này trong tài liệu Oracle JDBC. – yawn

-2

đây là thư viện tốt để kéo các kết quả java sql vào bộ nhớ.

http://casperdatasets.googlecode.com

bạn có thể cuộn/lặp qua các bộ dữ liệu, bạn có thể phát hành các truy vấn chống lại nó, và xây dựng các chỉ số để tối ưu hóa. nó cũng triển khai thực hiện giao diện java.sql.resultset để bạn có thể tiếp tục hoạt động trên các kết quả từ tập dữ liệu này với các biên bản tối thiểu cho mã jdbc của bạn.

+0

nó cũng có một bộ chuyển đổi sẽ chuyển đổi một kết quả jdbc thành một bộ nhớ trong bộ nhớ - tôi cho rằng bạn có thể gọi bộ điều hợp này trong phương thức gọi lại kết quả jdbc mùa xuân của bạn. –

+1

Xin lỗi, nhưng "cách lặp lại/cuộn qua các tập kết quả lớn (mà * sẽ không vừa với bộ nhớ *)". – yawn

5

Bạn có thể sử dụng thư viện springjdbc-iterable:

CloseableIterator<MyObj> iter = jt.queryForIter("select ...", params, mapper); 

Iterator sẽ được tự động đóng cửa vào kiệt sức hoặc có thể được đóng lại bằng tay. Nó sẽ chỉ hoạt động trong giới hạn giao dịch.

Disclaimer: Tôi đã viết thư viện này

0
  1. Tạo một thủ tục lưu trữ tùy chỉnh kéo dài StoredProcedure
  2. Tạo một RowCallBackHandler có thể xử lý mỗi hàng, cùng một lúc.
  3. Khai báo thông số của bạn. Nếu bạn có Tập kết quả, hãy khai báo kết quả đầu tiên. Sử dụng các lớp SqlReturnResultSet và tạo ra nó sử dụng của bạn RowCallBackHandler
  4. Declare bất kỳ thông số khác
  5. Compile
  6. tôi đã làm các bước từ 2 đến 5 trong constructor của khách hàng của tôi được lưu trữ thủ tục
  7. Tạo một bản đồ có chứa đầu vào của bạn thông số
  8. Thực hiện các thủ tục được lưu trữ của bạn với các thông số đầu vào

Tôi sẽ cung cấp mã, nhưng bài viết sau đây chứa tất cả thông tin này.

Calling Stored Procedures with Spring JDBC Templates

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