代码之家  ›  专栏  ›  技术社区  ›  niklassaers

Hibernate/Spring:在@Transactional中加载惰性集合时出错

  •  1
  • niklassaers  · 技术社区  · 14 年前

    更新:异常发生在行“type.getTranslatableText类型().size()“

    干杯

    // 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 回复  |  直到 14 年前
        1
  •  2
  •   Roman    14 年前

    下面是对 Open Session in View

    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) 您可以在视图过滤器(或OpenEntityManagerInViewFilter)中使用opensession,但这将使会话保持打开状态,直到页面加载完成(可能需要几秒钟)。

    3) 当您需要从数据库加载一些集合时,只需执行一个JPA查询并使用特殊的DAO方法(这意味着 translatableText CategoryType 类)。最强大的解决方案,但你需要做一些额外的工作来实现它,它比任何前2个选项更困难。