Hibernate / Spring: ошибка при загрузке отложенной коллекции в @Transactional - PullRequest
1 голос
/ 15 сентября 2010

Я, хотя и понимал ленивую / энергичную загрузку, но, очевидно, не понимаю:

У меня есть служба, помеченная @Transactional, но когда я пытаюсь манипулировать полученным списком (обращаясь к его объектам), я получаю «org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию ролей: tld.myproduct .data.entities.CategoryType.translatableText, ни один сеанс или сеанс не был закрыт ". Любые предложения о том, почему я не могу получить доступ к моим подчиненным объектам?

ОБНОВЛЕНИЕ: Исключение происходит в строке "type.getTranslatableText (). Size ()"

Приветствия

Nik

// The service
@Service("categoryTypeService")
@Transactional("transactionManager")
public class CategoryTypeServiceImpl extends AbstractCRUDServiceImpl<CategoryType, Integer> implements CategoryTypeService {

    @SuppressWarnings("unchecked")
    @Override
    public List<CategoryType> getAll() {
        List<CategoryType> list = DAO.getSession().createCriteria(CategoryType.class).list();

        for(CategoryType type : list)   
            type.getTranslatableText().size();  // Access TranslatableText to demonstrate problem

        return list;
    }

}


// The entity
@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@Configurable(preConstruction=true)
public class CategoryType {

    @Id
    @Column(nullable = false)
    private Integer id;

    @Column(length = 50, nullable = true)
    private String description;

    @Column(name = "TranslatableDescriptionId", nullable = false)
    private Integer TranslatableDescriptionId;

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(name = "Id", referencedColumnName="TranslatableDescriptionId", insertable=false, updatable=false)
    private Set<TranslatableText> translatableText;

    /** getters and setters **/
}

1 Ответ

2 голосов
/ 15 сентября 2010

Вот общее обсуждение проблемы Open Session in View . Я рекомендую вам прочитать статью.

Проще говоря, у вас есть 3 возможных решения:

1) не выполнять ленивую загрузку коллекции (конечно, если это не критично, производительность должна быть как-то проверена):

@OneToMany(fetch=FetchType.EAGER)   //   <-- it's not lazy any more
@JoinColumn(name = "Id", referencedColumnName="TranslatableDescriptionId", insertable=false, updatable=false)
private Set<TranslatableText> translatableText;

2) вы можете использовать Open Session в View Filter (или OpenEntityManagerInViewFilter), но это будет держать ваш сеанс открытым до завершения загрузки страницы (возможно, несколько секунд).

Это может вызвать проблемы с производительностью, и, скорее всего, вы получите ситуацию, когда один пользователь меняет объекты, в то время как другой пользователь имеет открытый сеанс гибернации. Я не знаю точно, что тогда произойдет, но вы должны это выяснить, если хотите быть уверенными в надежности своего приложения.

3) когда вам нужно загрузить некоторую коллекцию из БД, просто выполните запрос JPA и извлеките все необходимые данные специальным методом DAO (это означает, что поле translatableText исчезнет из класса CategoryType). Самое надежное решение, но вам нужно проделать дополнительную работу для его реализации, оно сложнее, чем любой из двух предыдущих вариантов.

...