2011-08-02 30 views
5

Tôi đang gặp phải một tình huống lạ khi tôi gặp vấn đề về tải chậm trên một trong các bộ điều khiển của mình. Lưu ý: Tôi đang sử dụng OpenSessionInViewInterceptor và đang chú thích lớp "dịch vụ" của tôi dưới dạng Giao dịch.Spring + Hibernate Lazy Load Error

Tôi có một vài cách khác nhau để tải đối tượng Person, một đối tượng bằng khóa và một bằng SSN. Về đối tượng con người của tôi, tôi có một bộ sưu tập các vai trò mà tôi tải xuống. Khi tôi tải bằng Khóa, tôi có thể truy cập danh sách như mong đợi. Khi tôi tải bằng SSN, tôi không thể truy cập danh sách.

Trong file cấu hình lớp dịch vụ của tôi, tôi đã thêm:

<tx:annotation-driven /> 

Đây là dịch vụ của tôi lớp mảnh mà tải các người bởi chính & SSN (Tôi biết điều này cần phải được trong một DAO/tái cơ cấu - đây code được thừa hưởng) - Lưu ý không phải phiên bản trong mảnh SSN cho phép tải - cả hai đều trong cùng một lớp:

@Transactional(readOnly = true, propagation = Propagation.REQUIRED) 
public Person loadPersonByKey(final Person.Key personKey) { 
    Assert.notNull(personKey); 
    return (Person) getHibernateTemplate().get(Person.class, personKey); 
} 

@Transactional(readOnly = true, propagation = Propagation.REQUIRED) 
public Person findPersonBySsn(final SocialSecurityNumber ssn) { 

    @SuppressWarnings("unchecked") 
    //List<Person> results = getHibernateTemplate().findByNamedParam("from core.model.entities.Person as person where ssn = :ssn", "ssn", ssn); 

    Criteria crit = getSession().createCriteria(Person.class); 
    crit.add(Restrictions.eq("ssn", ssn)); 
    List<Person> results = crit.list(); 

    int size = results.size(); 

    Person returnPerson = ((size != 0) ? (Person) results.get(0) : null); 
    return returnPerson; 
} 

sự khác biệt duy nhất trong bộ điều khiển của tôi là một tải bởi Key, và một tải bởi SSN. Đây là phần thích hợp của stacktrace:

SEVERE: Servlet.service() for servlet springmvc threw exception 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: core.model.entities.Person.memberships, no session or session was closed 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) 
at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:176) 
at org.hibernate.collection.PersistentMap.get(PersistentMap.java:169) 
at core.model.entities.Person.getMemberships(Person.java:870) 
at core.springmvc.controllers.find.FindController.defaultAction(FindController.java:164) 

Ghi chú lẻ, nếu tôi tải người đó bằng khóa ngay sau khi tải bởi SSN, tôi có thể đọc bộ sưu tập mà không có vấn đề.

Edit:

Dưới đây là các bản ghi trước khi stack trace:

2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Resetting read-only flag of JDBC Connection [Transaction-aware proxy for target Connection [jdbc:oracle:thin:@(description=(address_list=(address=(host=127.0.0.1)(protocol=tcp)(port=11523))(load_balance=yes)(failover=yes))), UserName=USER_NAME, Oracle JDBC driver]] 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.impl.SessionImpl CV#905cde28-e60c-4331 P#75004 - disconnecting session 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.springframework.jdbc.datasource.DataSourceUtils CV#905cde28-e60c-4331 P#75004 - Returning JDBC Connection to DataSource 
2011-08-02 13:29:32,415 [http-8080-1] DEBUG org.hibernate.jdbc.ConnectionManager CV#905cde28-e60c-4331 P#75004 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
+0

Ngoài ra nếu gọi Hibernate.initialize (người) tôi vẫn nhận được ngoại lệ khởi tạo - ngay cả khi tôi làm điều đó trong lớp dịch vụ. – Scott

Trả lời

2

Bạn không hiển thị đủ của stacktrace để xem nơi ngoại lệ được phát ra từ, nhưng tôi cho rằng đó là trong lớp xem của bạn. Đó là những gì phiên mở trong dạng xem là về. Bạn nói rằng bạn đang sử dụng OpenSessionInViewInterceptor, nhưng dường như bạn không cho nó một phạm vi đủ rộng. Các interceptor áp dụng cho các cuộc gọi phương thức. Tôi sẽ đoán rằng bạn đã áp dụng nó cho "dịch vụ" của bạn. Nếu có, bạn cũng có thể tắt nó đi. Nó không làm gì cả. Toàn bộ điểm của mẫu là để đảm bảo Phiên vẫn mở vượt quá ranh giới lớp dịch vụ. Đối với một ứng dụng web thông thường, OpenSessionInViewFilter là lựa chọn thích hợp.

+0

Đã thêm hai dòng theo dõi ngăn xếp tiếp theo. Nó chắc chắn không xảy ra bên trong quan điểm. – Scott

+0

@Scott: Bộ điều khiển nhóm thành "chế độ xem". Trình OpenSessionInViewInterceptor của bạn được áp dụng ở đâu? –

+0

Sử dụng OpenSessionInViewInterceptor chuẩn. Nó được áp dụng cho tất cả các yêu cầu được xử lý thông qua Dispatcher Servlet. Khi tôi gỡ lỗi thông qua bộ điều khiển làm việc và bộ điều khiển không làm việc tôi thấy rằng có một phiên mà Interceptor đang sử dụng. Một cái gì đó phải được cấu hình sai mặc dù, như các bộ sưu tập Persistent mà Hibernate kết thúc tốt đẹp xung quanh bộ sưu tập của tôi tải lazily cho thấy không có phiên khi gỡ lỗi. – Scott

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