org.hibernate.LazyInitializationException:懒得初始化一个角色集合:FQPropretyName,无法初始化代理 - 没有Session

zik*_*ack 10 spring-data-jpa spring-boot spring-boot-test

我正在尝试使用SpringBoot,SpringDataJpa以及使用SpringBootTest进行单元测试的ManyToOne双向关联.但是,测试失败,堆栈跟踪如下所示.但是我无法找到原因.任何指针都会有所帮助

Spring Boot JUnit Test下面的ManyToOne双向关联失败.

    @Test
    public void testFindByRegionIdEquals() {
        Region region = regionService.findByRegionIdEquals(1L);
        Region expectedRegion = new Region(1L, "Europe");
        assertThat(region).isNotNull().isEqualTo(expectedRegion);
        assertThat(region.getCountries()).isNotEmpty().doesNotContainNull().size().isEqualTo(8);
    }
Run Code Online (Sandbox Code Playgroud)

异常StackTrace

    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: zikzakjack.domain.Region.countries, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:587)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:204)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:148)
    at org.hibernate.collection.internal.PersistentSet.isEmpty(PersistentSet.java:149)
    at org.assertj.core.util.IterableUtil.isNullOrEmpty(IterableUtil.java:35)
    at org.assertj.core.internal.Iterables.assertNotEmpty(Iterables.java:152)
    at org.assertj.core.api.AbstractIterableAssert.isNotEmpty(AbstractIterableAssert.java:145)
    at zikzakjack.service.RegionServiceTests.testFindByRegionIdEquals(RegionServiceTests.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Run Code Online (Sandbox Code Playgroud)

拥有实体ManyToOne

@Data
@Entity
@Table(name = "COUNTRIES")
public class Country implements Serializable, Comparable<Country> {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "COUNTRY_ID")
    private String countryId;

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

    @ManyToOne
    @JoinColumn(name = "REGION_ID")
    private Region region;

    public Country() {

    }

    public Country(String countryId, String countryName, Region region) {
        super();
        this.countryId = countryId;
        this.countryName = countryName;
        this.region = region;
    }

}
Run Code Online (Sandbox Code Playgroud)

*带有mappedBy*的非拥有实体OneToMany

@Data
@Entity
@Table(name = "REGIONS")
public class Region implements Serializable, Comparable<Region> {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "REGION_ID")
    private Long regionId;

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

    @OneToMany(mappedBy = "region", fetch = FetchType.LAZY)
    private Set<Country> countries = new HashSet<Country>();

    public Region() {
    }

    public Region(Long regionId, String regionName) {
        this.regionId = regionId;
        this.regionName = regionName;
    }

    public Region(String regionName) {
        this.regionName = regionName;
    }

    public void addCountry(Country country) {
        countries.add(country);
        country.setRegion(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

zik*_*ack 20

好吧,我从这篇文章中找到答案/sf/answers/2708365131/

在application.properties中添加以下配置修复了问题:

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
Run Code Online (Sandbox Code Playgroud)

另一个对我有用的解决方案,但请注意,我仍然需要更多地了解它是如何解决这个问题的

@Transactional确保该测试方法中的所有方法调用都在同一边界内发生.

    @Test
    @Transactional
    public void testFindByRegionIdEquals() {
        Region region = regionService.findByRegionIdEquals(1L);
        Region expectedRegion = new Region(1L, "Europe");
        assertThat(region).isNotNull().isEqualTo(expectedRegion);
        assertThat(region.getCountries()).isNotEmpty().doesNotContainNull().size().isEqualTo(8);
    }
Run Code Online (Sandbox Code Playgroud)

  • ```enable_lazy_load_no_trans```是反模式导致n + 1问题不要使用它. (4认同)
  • 是的@YouYou。参见https://vladmihalcea.com/the-hibernate-enable_lazy_load_no_trans-anti-pattern/ (2认同)
  • 谢谢!测试中的@Transactional批注解决了我的问题(与您相同的问题) (2认同)