我虽然理解懒惰/急切的加载,但显然我没有:
我有一个标记为@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 **/
}
答案 0 :(得分:2)
以下是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)您可以在View Filter(或OpenEntityManagerInViewFilter)中使用Open Session,但这将使您的会话保持打开状态,直到页面加载完成(可能是几秒钟)。
它可能会导致性能问题,更有可能的是,当一个用户正在更改对象而另一个用户具有打开的休眠会话时,您将获得这种情况。我不知道到底发生了什么,但如果你想确保你的应用程序是健壮的,你应该找到它。
3)当你需要从数据库加载一些集合时,只需执行JPA查询并使用特殊的DAO方法获取所有必需的数据(这意味着字段translatableText
将从CategoryType
类中消失) 。最强大的解决方案,但你需要做一些额外的工作来实现它,它比以前的两个选项更难。