SpringBootTestを使用した単体テストとともに、SpringBoot、SpringDataJpaを使用したManyToOne Bi-Directional Associationを試しています。ただし、以下に示すスタックトレースでテストは失敗します。しかし、私は理由を見つけることができません。任意のポインターが役立ちます
ManyToOne Bi-Directional AssociationのSpring Boot JUnitテストの下で失敗します。
@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);
}
例外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)
所有エンティティ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;
}
}
* Non-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);
}
}
まあ、私はこの投稿から答えを見つけました https://stackoverflow.com/a/38690930/5266568
Application.propertiesに以下の構成を追加すると、問題が修正されました。
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
私のために働いた別の解決策ですが、それが実際に問題をどのように解決したかについてさらに理解する必要があることに注意してください
@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);
}