2014-09-16 4 views
0

Я борюсь с редактированием и обновлением вложенных объектов из-за этого Hibernate Lazy Ошибка загрузки, которую я продолжаю нажимать снова и снова.Hibernate no session error на прокси-объекте

В моем приложении:

  1. Я связать изображение Set к продукту.
  2. Я использовал форматтер для преобразования набора изображений для использования в поле выбора, чтобы пользователь мог выбрать набор изображений.
  3. Он хорошо работает, если форма завершается успешно, объект связывается, и отношения сохраняются правильно.
  4. Но если произошел сбой проверки, когда пользовательский интерфейс пытается получить доступ к вложенному объекту, я получаю страшную ошибку Lazy Initialization/No Session!

Так что я пытался написать метод, чтобы инициализировать соответствующие объекты как обходной путь:

@Transactional 
public void initObject(Variant variant) { 
    Hibernate.initialize(variant.getOption1()); 
    Hibernate.initialize(variant.getOption2()); 
    Hibernate.initialize(variant.getOption3()); 
    Hibernate.initialize(variant.getImageSet()); 
} 

Первые 3 строки в этом методе работы (они являются однонаправленными один к одному), но четвертый Безразлично 't (это много к одному), он по-прежнему не говорит прокси.

Я также пробовал сделать все.

Ни один из них не работал.

Проблема, вероятно, в том, что я создаю родительский объект, он не сохраняется в базе данных при наличии ошибки проверки, но вложенный объект по какой-либо причине является ленивым прокси-объектом независимо от типа выборки (см. форматтер ниже).

Как это исправить?

Это компонент форматировщик:

@Component 
public class ImageSetFormatter implements Formatter<ProductImageSet> { 

    private static Logger logger = LogManager.getLogger(VariantController.class.getName()); 

    @Autowired 
    private ProductImageService imageService; 

    @Override 
    public ProductImageSet parse(String s, Locale locale) throws ParseException { 
     logger.entry(); 

     Long imageSetId = Long.valueOf(s); 
     logger.exit(); 
     return imageService.getImageSet(imageSetId); 
    } 

    @Override 
    public String print(ProductImageSet productImageSet, Locale locale) { 
     logger.entry(); 

     logger.exit(); 
     return Long.toString(productImageSet.getId()); 
    } 
} 

StackTrace, когда линия Hibernate.initialize (variant.getImageSet()) называется:

org.springframework.web.util.NestedServletException : Запрос не выполнен; вложенное исключение org.hibernate.LazyInitializationException: не удалось инициализировать прокси - нет Session org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:973) org.springframework.web.servlet.FrameworkServlet.doPost (FrameworkServlet .java: 863) javax.servlet.http.HttpServlet.service (HttpServlet.java:644) org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:837) javax.servlet.http.HttpServlet. сервис (HttpServlet.java:725) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal (CharacterEncodingFilter.java:88) org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) org.springframework .web.f ilter.HiddenHttpMethodFilter.doFilterInternal (HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java: 330) org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:113) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:342) org.springframework.security.web.session.SessionManagementFilter.doFilter (SessionManagementFilter.java:103) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain. doFilter (FilterChainProxy.java:342) org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:113)

Соответствующие отношения Объект:

@Entity 
@Table(name="variants") 
@EntityListeners({AuditingEntityListener.class}) 
public class Variant extends AbstractAuditable<Customer, Long> { 

    @OneToOne 
    private VariantOptionValue option1; 

    @OneToOne 
    private VariantOptionValue option2; 

    @OneToOne 
    private VariantOptionValue option3; 

    ... 

    @ManyToOne 
    @JoinColumn(name="image_set_id") 
    @LazyCollection(LazyCollectionOption.FALSE) 
    private ProductImageSet imageSet; 



} 


@Entity 
@Table(name="product_image_set") 
@EntityListeners({AuditingEntityListener.class}) 
public class ProductImageSet extends AbstractAuditable<Customer, Long> { 


    public ProductImageSet(String label) 
    { 
     this.label = label; 
    } 

    public ProductImageSet(){ 

    } 

    @Basic 
    @Column(length = 50, nullable = false) 
    private String label; 

    @OneToMany(mappedBy = "imageSet", fetch = FetchType.EAGER) 
    private List<ProductImage> images; 

    @OneToMany(mappedBy = "imageSet", fetch = FetchType.EAGER) 
    private List<Variant> variants; 

    private int sequence; 

    @ManyToOne 
    @JoinColumn(name = "product_id") 
    private Product product; 

    ... 
} 
+0

Вы можете разместить фактическое StackTrace от исключением того, что вы получаете? Сообщение об ошибке может дать представление о том, что такое ошибка. Можете ли вы также опубликовать свои объекты, которые вы используете, или дать подробное описание их отношений (один X имеет много Y, один Y имеет один Z и т. Д.) – JamesENL

+0

Можете ли вы опубликовать описание объектных отношений? Вы говорите о родительском объекте, но мне нужно знать, что является родителем, а что является дочерним. – JamesENL

+0

Обратите внимание, что я пробовал несколько вариантов уже из fetch = FetchType.EAGER, LazyCollection был моей последней попыткой исправить. –

ответ

0

две вещи, которые могли бы хочу попробовать.

1- добавить OpenEntityManagerInViewFilter

<filter> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
    <init-param> 
     <param-name>entityManagerFactoryBeanName</param-name> 
     <param-value>entityManagerFactory</param-value> 
    </init-param> 
</filter> 

<filter-mapping> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

2- Добавить организации/вид/модель на сессии

@Controller 
@SessionAttributes("yourEntityFormModel") 
public class YourController { 
    ... 
} 

--------- Обновление

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

Итак, приведенный ниже пример отлично работает.

@Transactional 
public void updateEmployeesFromDepartment(int depId) { 

    Department dep = departmentRepository.findOne(dep.getId()); 
    for (Employee e : dep.getEmployees()) { 
     // update whatever you want 
    } 

} 

Но я не ожидаю, что это работает ...

public void updateEmployeesFromDepartment(int depId) { 

    Department dep = departmentRepository.findOne(dep.getId()); 
    for (Employee e : dep.getEmployees()) { 
     // update whatever you want 
    } 

} 
+0

См. [This] (http://stackoverflow.com/questions/1538222/why-not-to-use-springs-openentitymanagerinviewfilter), почему номер 1 - плохая идея. – JamesENL

+0

Кроме того, если это приложение RESTful, номер 2 полностью уничтожает любую реализацию RESTful, поскольку вы делаете ее с сохранением состояния, добавляя модель к сеансу. – JamesENL

+0

@JamesMassey Я понимаю суть ... спорный ... Это один из тех партнеров, который однажды спас день, но людям (!?!) Больше не нравится. Я предпочитаю загружать всю необходимую информацию для просмотра заранее, но если я могу помочь другу здесь, он может решить позже, нравится ли ему это или нет. :) – Desorder