0

由于我不断遇到的 Hibernate Lazy Loading 错误,我正在努力编辑和更新嵌套对象。

在我的应用程序中:

  1. 我将图像集绑定到产品。
  2. 我使用格式化程序转换图像集以在选择框中使用,因此用户可以选择图像集。
  3. 如果表单成功,对象绑定并且关系正确保存,则效果很好。
  4. 但是,如果验证失败,每当 UI 层尝试访问嵌套对象值时,我都会收到可怕的延迟初始化/无会话错误!

所以我尝试编写一个方法来初始化相关对象作为解决方法:

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

该方法中的前 3 行有效(这些是单向的一对一),但第四行无效(这是多对一),它仍然表示没有代理。

我也尝试过制作所有 Eager fetch 类型。

这些都不起作用。

问题可能是我正在创建父对象,当出现验证错误时它不会保存到数据库中,但是无论出于何种原因,嵌套对象都是惰性代理对象,无论获取类型如何(请参阅下面的格式化程序) .

我怎样才能解决这个问题?

这是格式化程序组件:

@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());
    }
}

调用 Hibernate.initialize(variant.getImageSet()) 行时的堆栈跟踪:

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常是 org.hibernate.LazyInitializationException: 无法初始化代理 - 没有会话 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:第863章725) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) org.springframework.web.filter.HiddenHttpMethodFilter。

相关对象关系:

   @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;

    ...
}
4

1 回答 1

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
    }

}
于 2014-09-16T02:57:58.467 回答