【发布时间】:2014-08-14 14:55:37
【问题描述】:
我正在开发一个基于 Spring Boot 的 Web 应用程序。我严重依赖 @ComponentScan 和 @EnableAutoConfiguration 并且没有明确的 XML 配置。
我有以下问题。我有一个名为 UserSettings 的 JPA-带注释的实体类:
@Entity public class UserSettings {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToMany(cascade = CascadeType.ALL)
private Set<Preference> preferences; // 'Preference' is another @Entity class
public UserSettings() {
this.preferences = new HashSet<Preference>();
}
// some more primitive properties, Getters, Setters...
}
我按照this 教程创建了一个扩展JpaRepository<UserSettings,Long> 的存储库接口。
此外,我有一个UserManager bean:
@Component public class SettingsManager {
@Autowired
UserSettingsRepository settingsRepository;
@PostConstruct
protected void init() {
// 'findGlobalSettings' is a simple custom HQL query
UserSettings globalSettings = this.settingsRepository.findGlobalSettings();
if (globalSettings == null) {
globalSettings = new UserSettings();
this.settingsRepository.saveAndFlush(globalSettings);
}
}
稍后在代码中,我再次使用findGlobalSetttings 查询加载此处创建的UserSettings 对象。
问题是:每次我尝试访问设置对象的@OneToMany属性时,都会出现以下异常:
org.hibernate.LazyInitializationException: 无法延迟初始化角色 org.example.UserSettings.preferences 的集合,无法初始化代理 - 没有会话
我了解每个 HTTP 会话都有自己的休眠会话,如this question 的接受答案中所述,但这不适用于我的情况(目前我正在同一个 HTTP 会话中对此进行测试),即为什么我不知道这个异常是从哪里来的。
我做错了什么,如何避免错误?
【问题讨论】:
-
休眠会话不是 Http 会话。一旦您的交易结束,休眠会话就会关闭。不是附加到 http 会话的休眠会话。它附加到当前事务(或在查看请求时将其与打开的会话/实体管理器一起使用)。
-
感谢您指出这一点。但是,我相信错误存在于 Spring 在运行时自动生成的 JpaRepository 类的实现中。我只是尝试使用 EntityManager 直接检索所需的实例——效果很好。使用 JpaRepository 进行相同的检索会产生具有相同 ID (!) 的同一类的对象,但该对象在 == 运算符方面与实体管理器返回的对象不同...
-
不,这不是同一个问题,与 Spring Data 无关。从 2 个不同的实体管理器中检索对象将始终为您提供另一个对象。问题很简单,因为您将引用存储在 http 会话中,当您尝试从会话中对该实体执行操作时,原始休眠会话就消失了。每次需要时检索它,或者在将对象放入会话之前完全初始化它。
-
我只是仔细检查了一遍:底层 Hibernate 'Session' 对象在存储我的 UserSettings 对象时与检索 UserSettings 对象时具有相同的 Java 对象 ID。据我所知(我使用 Vaadin 作为 Web UI 工具包和 Vaadin4Spring),我仍然在同一个 HTTP 会话和请求中。无论如何,在存储和查询它时我得到了一个不同的 UserSettings 对象,并且我得到了上述异常。
-
正如在事务结束后会话关闭之前两次所述,除非您在视图中使用打开的会话,这将保持休眠会话直到呈现视图。否则,一旦 tx 完成,休眠会话就会消失。
标签: spring hibernate jpa spring-data spring-boot