2013-05-25 11 views
27

Tôi đã có một lỗi mà trông như thế này:Không thể khởi tạo proxy - không có phiên

Không thể khởi tạo proxy - không có phiên

Tôi đang làm việc với java, hibernate và mùa xuân . Lỗi này xuất hiện khi cố tạo một tài liệu PDF, và tôi đang làm theo các bước tiếp theo để tạo ra nó một cách nhanh chóng và lưu trữ trong cơ sở dữ liệu.

  1. Tôi đã gửi yêu cầu đến ứng dụng thông qua phương thức POST. Điều này tạo ra các PDF trên bay và hiển thị cho người dùng.

  2. Ngay sau yêu cầu đó tôi gửi một yêu cầu khác, nhưng thông qua yêu cầu ajax. Điều này sẽ tạo ra cùng một tệp PDF nhưng sẽ lưu nó trong DB.

Lỗi này cho thấy không thể thực thi truy vấn do lỗi "không thể khởi chạy proxy - không phiên".

Có điều gì mà tôi đang làm sai, gọi các phương thức giống nhau hai lần từ cùng một phiên người dùng không? Có thể là phiên được đóng trước khi cả hai yêu cầu đã kết thúc?

Hy vọng ai đó có thể giúp tôi hiểu điều gì đang xảy ra.

+0

Lỗi sang một bên, tại sao bạn thực hiện hai cuộc gọi riêng biệt để tạo tệp PDF? Làm điều đó một lần, duy trì nó, sau đó lấy nó từ cơ sở dữ liệu để thay thế. – Makoto

+0

Khi tôi đang viết câu hỏi, tôi nghĩ như bạn đang đề xuất. Nhưng tôi muốn ai đó có thêm một chút kinh nghiệm xác nhận như vậy. Và chỉ để làm cho nó hữu ích hơn ... Bạn có thể giải thích tại sao lỗi "không thể khởi tạo proxy - không phiên" xảy ra trong kịch bản specifi này không ?. cảm ơn trước. –

+0

Hibernate issue. Hiển thị cho chúng tôi mã đằng sau cuộc gọi Ajax để chúng tôi có thể giúp bạn. – Jukka

Trả lời

67

Vấn đề của bạn là phiên ngủ đông chỉ tồn tại cho một yêu cầu. Nó mở ra khi bắt đầu yêu cầu và đóng vào cuối. Bạn đoán câu trả lời: Phiên Hibernate bị đóng trước khi cả hai yêu cầu được hoàn tất.

Chính xác những gì đang xảy ra? Các đối tượng thực thể của bạn sống trong cả hai yêu cầu. Làm sao? Chúng được lưu trữ trong phiên HTTP (một phiên khác gọi là session) Bạn không cung cấp nhiều thông tin về framework mà bạn đang sử dụng, vì vậy tôi không thể cung cấp thêm chi tiết, nhưng chắc chắn rằng framework bạn đang sử dụng bằng cách nào đó giữ các thực thể của bạn trong phiên HTTP. Đây là cách khuôn khổ giúp bạn dễ dàng làm việc với cùng một đối tượng cho nhiều yêu cầu.

Khi xử lý yêu cầu thứ hai bắt đầu, mã đang cố gắng truy cập một số thực thể (thường là một phần tử của bộ sưu tập) được khởi tạo lười biếng bằng ngủ đông. Thực thể không được gắn vào một phiên ngủ đông, và vì vậy hibernate không thể khởi tạo proxy hibernate trước khi đọc nó. Bạn nên mở một phiên và đính kèm lại thực thể của bạn vào nó khi bắt đầu xử lý yêu cầu ajax.

EDIT:

Tôi sẽ cố gắng để đưa ra một lời giải thích ngắn gọn về những gì đang xảy ra đằng sau những cảnh. Tất cả các khung công tác web java đều có một hoặc nhiều servlet xử lý các yêu cầu. Servlet xử lý mỗi yêu cầu (HttpRequest) bằng cách tạo ra một luồng mới mà cuối cùng sẽ tạo ra phản hồi (HttpResponse). Phương thức xử lý từng yêu cầu được thực thi bên trong luồng này.

Khi bắt đầu xử lý yêu cầu, ứng dụng của bạn nên phân bổ các tài nguyên cần để xử lý (Giao dịch, phiên Hibernate, v.v.). Vào cuối chu kỳ xử lý các tài nguyên này được phát hành (Giao dịch được cam kết, phiên ngủ đông được đóng lại, các kết nối JDBC được phát hành, vv). Vòng đời của các tài nguyên này có thể được quản lý bởi khung của bạn hoặc có thể được thực hiện bằng mã của bạn.

Để hỗ trợ trạng thái ứng dụng trong giao thức không trạng thái như HTTP, chúng tôi có đối tượng HttpSession. Chúng tôi (hoặc các khung công tác) đưa vào HttpSession thông tin vẫn còn liên quan giữa các chu kỳ yêu cầu khác nhau của cùng một khách hàng.

Trong quá trình xử lý yêu cầu đầu tiên hibernate đọc (lazily) một thực thể từ cơ sở dữ liệu. Do khởi tạo lười biếng, một số phần của cấu trúc của đối tượng này là các đối tượng proxy hibernate. Các đối tượng này được kết hợp với phiên ngủ đông đã tạo chúng.

Khuôn khổ tìm thấy thực thể từ yêu cầu trước đó trong đối tượng HttpSession khi bạn cố xử lý yêu cầu thứ hai. Sau đó, nó đang cố gắng truy cập vào một thuộc tính từ một thực thể con đã được tạo ra một cách lười biếng và bây giờ là một đối tượng proxy ngủ đông. Các đối tượng proxy hibernate là một giả của đối tượng thực sự sẽ yêu cầu phiên ngủ đông của nó để điền nó với thông tin từ cơ sở dữ liệu khi ai đó cố gắng truy cập vào một trong các thuộc tính của nó. Điều này proxy hibernate của bạn đang cố gắng làm. Nhưng phiên của nó đã được đóng lại vào cuối quá trình xử lý yêu cầu trước đó, do đó, bây giờ nó không có một phiên ngủ đông để sử dụng để được ngậm nước (chứa đầy thông tin thực). Lưu ý rằng có thể bạn đã mở một phiên ngủ đông ở đầu yêu cầu thứ hai, nhưng nó không nhận thức được thực thể chứa đối tượng proxy vì thực thể này được đọc bởi một sesion ngủ đông khác. Bạn nên gắn lại thực thể vào phiên ngủ đông mới.

Có rất nhiều cuộc thảo luận về cách đính kèm lại một thực thể tách rời, nhưng cách tiếp cận đơn giản nhất ngay bây giờ là session.update(entity).

Hy vọng điều đó sẽ hữu ích.

+0

Im sử dụng lò xo. Vì vậy, theo câu trả lời của bạn yêu cầu đầu tiên làm việc với các thông tin lấy từ cơ sở dữ liệu bằng cách sử dụng ngủ đông. Sau đó, yêu cầu thứ hai đến và cố gắng truy cập vào cùng một dữ liệu thực hiện truy vấn không thành công vì yêu cầu đầu tiên đóng phiên ngủ đông trước khi yêu cầu thứ hai kết thúc công việc của nó. Tôi có đúng không? –

+0

Bạn đã hiểu. Cùng một dữ liệu bạn đề cập đến là thực thể tồn tại trong phiên người dùng của bạn (HttpSession). Trong yêu cầu thứ hai hibernate đang cố gắng điền vào đối tượng proxy (mà là một giả của đối tượng thực) với thông tin từ cơ sở dữ liệu. Trước khi cố gắng thực hiện các truy vấn sẽ lấy dữ liệu, hibernate cố gắng tìm đối tượng phiên làm việc ngủ đông được liên kết với đối tượng proxy này. Nhưng đối tượng proxy không được kết hợp với một phiên ngủ đông. Thực thể cha của đối tượng proxy đã được tách ra khỏi phiên khi yêu cầu đầu tiên kết thúc. – nakosspy

+0

được chỉnh sửa với một số chi tiết khác về chu kỳ xử lý yêu cầu – nakosspy