【问题标题】:failed to lazily initialize a collection of role... could not initialize proxy - no Session - @Transactional not working无法懒惰地初始化角色集合...无法初始化代理 - 没有会话 - @Transactional 不起作用
【发布时间】:2021-08-20 21:58:23
【问题描述】:

我在学习 Hibernate OneToMany 时遇到问题。 我的测试代码有一个有很多书的学生。

@OneToMany(
            mappedBy = "student",
            orphanRemoval = true,
            cascade = {CascadeType.PERSIST, CascadeType.REMOVE}
    )
    private List<Book> books = new ArrayList<>();

正如预期的那样,当我尝试阅读学生并访问书籍时,标题错误中提到了我,因为 OneToMany 中的默认行为是 LAZY。

@Transactional
    private void testowy(StudentRepository studentRepository){
        studentRepository.findById(4L).ifPresent(
                s -> {

                    System.out.println(s);

                    s.addBook(new Book(LocalDateTime.now(),"pozycja1"));

                    studentRepository.save(s);
                }
        );
    }
failed to lazily initialize a collection of role: com.example.demo.Student.books, could not initialize proxy - no Session

但是正如你所看到的,我在 google/stacoverflow 上搜索了一下,发现如果我使用 @Transactional 注释,会话不应该被破坏。但它对我不起作用。

我也尝试了属性“enable_lazy_load_no_trans = true”,它也没有解决问题,但我不知道这是否是我想要去的方向......

我该如何解决这个错误,@Transactional 注释我做错了什么? (来自导入 org.springframework.transaction.annotation.Transactional;)

failed to lazily initialize a collection of role: com.example.demo.Student.books, could not initialize proxy - no Session

编辑: 关于将私有更改为公共的提议,它没有帮助。

@Transactional
    public void testowy(StudentRepository studentRepository){
        System.out.println("-------before-----------");
        studentRepository.findById(4L).ifPresent(
                s -> {

                    System.out.println("------------------");
                        System.out.println(s);
                    System.out.println("------------------");

                    System.out.println("-------add-----------");
                    s.addBook(new Book(LocalDateTime.now(),"pozycja1"));
                    System.out.println("---------save---------");
                    studentRepository.save(s);
                }
        );
    }

没有帮助:

-------before-----------
Hibernate: 
    select
        student0_.id as id1_2_0_,
        student0_.age as age2_2_0_,
        student0_.email as email3_2_0_,
        student0_.first_name as first_na4_2_0_,
        student0_.last_name as last_nam5_2_0_,
        studentidc1_.id as id1_3_1_,
        studentidc1_.card_number as card_num2_3_1_,
        studentidc1_.student_id as student_3_3_1_ 
    from
        student student0_ 
    left outer join
        student_id_card studentidc1_ 
            on student0_.id=studentidc1_.student_id 
    where
        student0_.id=?
------------------
2021-06-02 20:19:06,148  INFO  [        main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 
2021-06-02 20:19:06,170  ERROR [        main] o.springframework.boot.SpringApplication : Application run failed 
java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298)
    at com.example.demo.Application.main(Application.java:20)
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.Student.books, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:621)
    at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453)
    at com.example.demo.Student.toString(Student.java:144)
    at java.base/java.lang.String.valueOf(String.java:3365)
    at java.base/java.io.PrintStream.println(PrintStream.java:1047)
    at com.example.demo.Application.lambda$testowy$1(Application.java:60)
    at java.base/java.util.Optional.ifPresent(Optional.java:178)
    at com.example.demo.Application.testowy(Application.java:56)
    at com.example.demo.Application.lambda$commandLineRunner$0(Application.java:39)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
    ... 5 common frames omitted

【问题讨论】:

    标签: spring spring-boot hibernate jpa


    【解决方案1】:

    如果没有额外的配置,Spring AOP 对私有方法不起作用,所以改为公共方法

    @Transactional
    public void testowy(StudentRepository studentRepository){
    

    【讨论】:

    • 显然它是一个 @Component 主体,对吧?
    • 我更新了主题,公开方法没有帮助。你是什​​么意思@Component?应该放在哪里?
    • 在你运行代码的类上
    • 我在主类中使用@SpringBootApplication 注解运行这段代码我不知道“@Component”对于这个类是否正确,但我可以试试。
    • 或者你的意思是我必须将此方法移动到不同于主 SpringBoot 类的类?
    猜你喜欢
    • 2021-06-15
    • 2016-11-10
    • 2014-05-03
    • 2020-11-25
    • 2021-01-30
    • 1970-01-01
    • 2016-06-04
    • 2018-11-21
    • 2014-12-23
    相关资源
    最近更新 更多