Play框架 + Spring Data JPA:延迟初始化异常

3
以下是相关的类:

@Entity
public class Question {
   @Id
   public Long id;
   public String name;

   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
   @JoinColumn(name = "OWNER_ID", referencedColumnName = "QUES_ID")
   public List<Choice> choices = new ArrayList<>();
}

@Named
@Singleton
public interface QuestionRepository extends CrudRepository<Question , Long> {
    Question findByName(String name);
}

在控制器文件中,我有以下文件:
@Transactional
public Result getQuestion() {
    List<Choices> list = this.questionRepository.findByName("name").choices;
    list.size();
    return ok();
}

在getQuestion()中,list.size()会抛出LazyInitializationException异常,因为没有打开会话。

我知道将获取类型更改为EAGER或在QuestionRepository中的函数定义上方使用JPQL查询可能会解决此问题,但是我的应用程序的某些部分无法帮助我并且我需要进行延迟获取。

如何使getQuestion()函数中的整个代码使用单个会话/事务,甚至更好的是,使我的整个请求在一个会话/事务中进行?


我认为Spring无法在getQuestion中开始一个事务,你只是使用了Spring Data的内部事务。 - Ali Dehghani
所有的 Repository 实现默认都是事务性的。当你调用 findByName 方法时,Spring 会开始一个事务,当方法返回时,事务会提交并且由于会话已关闭,list.size() 抛出 LazyInitializationException 异常。请检查 Play/Spring 集成。 - Ali Dehghani
你可以参考https://dev59.com/VoTba4cB1Zd3GeqP9KvQ#26615390。 - Harshal Patil
1个回答

2

来自Spring Data JPA参考文档

的内容:

4.7.1. Transactional query methods

To allow your query methods to be transactional simply use @Transactional at the repository interface you define.

Example 100. Using @Transactional at query methods

@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {

    List<User> findByLastname(String lastname);

    @Modifying 
    @Transactional
    @Query("delete from User u where u.active = false")  
    void deleteInactiveUsers();
}

Typically you will want the readOnly flag set to true as most of the query methods will only read data. In contrast to that deleteInactiveUsers() makes use of the @Modifying annotation and overrides the transaction configuration. Thus the method will be executed with readOnly flag set to false.

所以只需要将@Transactional注解添加到您的存储库接口中即可。


如上所述,我希望找到一种无需@Query的解决方案,该解决方案使会话/事务在UserRepository之外可用。 - AbrahamDaniel
不需要查询,只需在接口中添加Transactional。 - mavarazy
添加事务没有起作用,getQuestion是我的控制器类的成员,而不是存储库接口。 - AbrahamDaniel
检查事务传播,基本上您希望将事务设置为“REQUIRED”传播到存储库和方法中。 - mavarazy
我希望能得到更详细的解释,如果有链接就更好了。谢谢。 - AbrahamDaniel
1
实际上需要一个默认配置。请检查您的Spring配置中是否启用了事务(@EnableTransactionManagement或<tx:annotation-driven/>是否存在)?并且在两个位置都只保留@Transaction。 - mavarazy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接