Java Spring引导中的延迟加载

Java Spring引导中的延迟加载,java,spring,spring-boot,Java,Spring,Spring Boot,我有两个实体,我使用多对多关系将它们连接起来 package com.app.mms.entity; import ... @Entity @Table(name = "insurance_company") public class InsuranceCompany{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "name"

我有两个实体,我使用多对多关系将它们连接起来

package com.app.mms.entity;

import ...

@Entity
@Table(name = "insurance_company")
public class InsuranceCompany{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "name")
    private String name;

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(name = "insurance_survey",
            joinColumns = { @JoinColumn(name = "id_insurance_company") },
            inverseJoinColumns = { @JoinColumn(name = "id_survey_company") })
    private List<SurveyCompany> surveyCompany;

   // Getters, setters and constructor
}
我试图懒洋洋地检索实体,但我遇到了一个异常:

System.out.println("All Survey companies:");
System.out.println(surveyCompanyDao.findAll());

System.out.println("All Insurance companies:");
System.out.println(insuranceCompanyDao.findAll());

// I imagine, after calling findAll() the session is already closed, 
//and then I try to retrieve the insurance company for that survey company because of lazy, and I get exception.
System.out.println(insuranceCompanyDao.findAll().get(0).getSurveyCompany());
例外情况是:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.mms.entity.InsuranceCompany.surveyCompany, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:602) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:217) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:581) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:148) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:537) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
    at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_112]
    at java.io.PrintStream.println(PrintStream.java:821) ~[na:1.8.0_112]
    at com.app.mms.MmsApplication.run(MmsApplication.java:63) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813) [spring-boot-2.1.4.RELEASE.jar:2.1.4.RELEASE]
    ... 10 common frames omitted
如何在Spring boot中懒洋洋地检索数据?我找到了一些解决方案,其中他们再次初始化会话(spring boot在存储库中默认提供)。我不太确定这样做是否正确,因为我对SpringBoot很陌生。如果有人能解释一下在spring boot中懒洋洋地检索数据的正确方法,那就太好了

编辑

package com.app.mms;

import ...

@SpringBootApplication
public class MmsApplication implements CommandLineRunner{

    @Autowired
    InsuranceCompanyDao insuranceCompanyDao;

    @Autowired
    SurveyCompanyDao surveyCompanyDao;

   @Autowired
   InsuranceCompanyService service;


    public static void main(String[] args) {
        SpringApplication.run(MmsApplication.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        System.out.println("In command line runner...");

        System.out.println("All Survey companies:");
        System.out.println(surveyCompanyDao.findAll());

        System.out.println("All Insurance companies:");
        System.out.println(insuranceCompanyDao.findAll());

     InsuranceCompany ic = insuranceCompanyDao.findAll().get(0);            
        System.out.println(service.getSurveyCompany(ic));

    }
}
我的主课

package com.app.mms;

import ...

@SpringBootApplication
public class MmsApplication implements CommandLineRunner{

    @Autowired
    InsuranceCompanyDao insuranceCompanyDao;

    @Autowired
    SurveyCompanyDao surveyCompanyDao;

   @Autowired
   InsuranceCompanyService service;


    public static void main(String[] args) {
        SpringApplication.run(MmsApplication.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        System.out.println("In command line runner...");

        System.out.println("All Survey companies:");
        System.out.println(surveyCompanyDao.findAll());

        System.out.println("All Insurance companies:");
        System.out.println(insuranceCompanyDao.findAll());

     InsuranceCompany ic = insuranceCompanyDao.findAll().get(0);            
        System.out.println(service.getSurveyCompany(ic));

    }
}
我的服务级别:

import ...

@Service
public class InsuranceCompanyService {
@Autowired
InsuranceCompanyDao insuranceCompanyDao;

 @Transactional 
 public List<SurveyCompany> getSurveyCompany(InsuranceCompany insuranceCompany){ 
 List<SurveyCompany> surveyCompanies = insuranceCompany.getSurveyCompany(); 
return surveyCompanies; 
} 
}
导入。。。
@服务
公共类保险公司服务{
@自动连线
保险公司DAO保险公司DAO;
@交易的
公共列表getSurveyCompany(保险公司保险公司){
List surveyCompanies=insuranceCompany.getSurveyCompany();
返回调查公司;
} 
}

将代码放入事务中,这样会话就不会关闭。另外,修复映射:它不正确。所以我需要在JpaRepository和访问数据之间创建一个服务?所以我可以使用事务性的方法将我的服务方法包装到事务中,对吗?我将更正映射,谢谢。或者使您当前正在执行的任何方法都具有事务性(即包装所有这些System.out.println语句的方法)。@transactional public void printSurvey(){System.out.println(insuranceCompanyDao.findAll().get(0.getSurveyCompany());}我尝试了这个,但是它仍然抛出相同的错误,所以您确实从同一类的另一个方法调用了事务方法。那不行。必须从外部调用该方法,以便事务代理拦截该方法。使run()方法本身具有事务性应该可以工作。将代码放入事务中,这样会话就不会关闭。另外,修复映射:它不正确。所以我需要在JpaRepository和访问数据之间创建一个服务?所以我可以使用事务性的方法将我的服务方法包装到事务中,对吗?我将更正映射,谢谢。或者使您当前正在执行的任何方法都具有事务性(即包装所有这些System.out.println语句的方法)。@transactional public void printSurvey(){System.out.println(insuranceCompanyDao.findAll().get(0.getSurveyCompany());}我尝试了这个,但是它仍然抛出相同的错误,所以您确实从同一类的另一个方法调用了事务方法。那不行。必须从外部调用该方法,以便事务代理拦截该方法。使run()方法本身具有事务性应该是可行的。
package com.app.mms;

import ...

@SpringBootApplication
public class MmsApplication implements CommandLineRunner{

    @Autowired
    InsuranceCompanyDao insuranceCompanyDao;

    @Autowired
    SurveyCompanyDao surveyCompanyDao;

   @Autowired
   InsuranceCompanyService service;


    public static void main(String[] args) {
        SpringApplication.run(MmsApplication.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        System.out.println("In command line runner...");

        System.out.println("All Survey companies:");
        System.out.println(surveyCompanyDao.findAll());

        System.out.println("All Insurance companies:");
        System.out.println(insuranceCompanyDao.findAll());

     InsuranceCompany ic = insuranceCompanyDao.findAll().get(0);            
        System.out.println(service.getSurveyCompany(ic));

    }
}
import ...

@Service
public class InsuranceCompanyService {
@Autowired
InsuranceCompanyDao insuranceCompanyDao;

 @Transactional 
 public List<SurveyCompany> getSurveyCompany(InsuranceCompany insuranceCompany){ 
 List<SurveyCompany> surveyCompanies = insuranceCompany.getSurveyCompany(); 
return surveyCompanies; 
} 
}