illegally attempted to associate proxy with two open Sessions 에러
SpringBatch와 Jpa를 사용하면서 illegally attempted to associate proxy with two open Sessions
에러를 만나게 됐다.
당연하지만 처음 보는 에러는 정말 당황스럽다.
illegally attempted to associate proxy with two open Sessions
에러는 두개 session에서 같은 proxy를 다루려 하면서 나타나는 에러다.
public MatchInfo process(MatchInfo matchInfo) throws Exception {
initializeUnitsAndAugments(matchInfo);
List<Augment> augments = getAugmentsByMatchInfo(matchInfo);
List<Unit> units = getUnitsByMatchInfo(matchInfo);
UseDeckAugment useDeckAugment = useDeckAugmentService.findOrSaveByAugmentsAndSeason(augments, matchInfo.getSeason());
...
}
위 코드를 보자, SpringBatch ItemReader를 통해 matchInfo
를 받아와 findOrSaveByAugmentsAndSeason
에서 matchInfo.getSeason()
값을 넘겨주었다.
@Transactional
public UseDeckAugment findOrSaveByAugmentsAndSeason(List<Augment> augments, Season season) {
Optional<UseDeckAugment> useDeckAugmentOptional = useDeckAugmentRepository.searchByAugmentsAndSeason(augments, season);
UseDeckAugment useDeckAugment;
if (useDeckAugmentOptional.isPresent()) {
useDeckAugment = useDeckAugmentOptional.get();
} else {
useDeckAugment = UseDeckAugment.builder()
.season(season)
.useCount(0L)
.build();
augments.stream()
.map(augment ->
UseAugment.builder()
.augment(augment)
.build()
)
.forEach(useDeckAugment::insertUseAugment);
useDeckAugmentRepository.save(useDeckAugment);
}
return useDeckAugment;
}
findOrSaveByAugmentsAndSeason
는 넘겨받은 season과 augment를 이용해 엔티티를 생성한다.
처음 해당 에러를 만났을 때, Season season = seasonRepository.findById(season.getId());
형태로 season을 새로 조회하여 해결하였다.
풀리지 않은 의문점은 똑같이 넘겨준 augments는 정상적으로 사용하는데 왜 season은 그렇지 않을까?였다.
2022-07-01 19:13:26.266 INFO 27878 --- [ main] c.h.a.service.UseDeckAugmentService : season: com.heekng.api_toche_web.entity.Season@440d45c5
이유는 matchInfo의 season 객체가 proxy객체라는 것이였다.
public MatchInfo process(MatchInfo matchInfo) throws Exception {
initializeUnitsAndAugments(matchInfo);
List<Augment> augments = getAugmentsByMatchInfo(matchInfo);
List<Unit> units = getUnitsByMatchInfo(matchInfo);
UseDeckAugment useDeckAugment = useDeckAugmentService.findOrSaveByAugmentsAndSeason(augments, matchInfo.getSeason());
...
}
위의 initializeUnitsAndAugments
는 units와 augments를 영속화하는 함수이다.
한번 영속화한 augments는 객체가 넘어가 사용되지만, matchInfo의 season은 영속화되지 않아 proxy 객체가 사용된 것이다.
또한 findOrSaveByAugmentsAndSeason
내에서 proxy 객체를 영속화하지 않았기 때문에 에러가 발생했다.
// initializeUnitsAndAugmentsAndSeason
...
Hibernate.initialize(matchInfo.getSeason());
위와 같이 Units와 Augments를 영속화하는 단게에서 season도 영속화하도록 수정하여 해결하였다.
'Java & Kotlin > Spring Data' 카테고리의 다른 글
[JPA] Cascade persist와 연관관계 (0) | 2022.06.24 |
---|---|
[QueryDSL] oneToMany 관계에서 여러 개의 fetchJoin 사용하기 (0) | 2022.06.24 |
[QueryDSL] gradle querydsl 설정하기 (0) | 2022.05.15 |
[QueryDSL] 페이징 연동하기 (0) | 2022.05.15 |
[QueryDSL] Spring Data JPA와 QueryDSL 사용하기 (0) | 2022.05.15 |
[QueryDSL] 벌크연산과 SQL Funtion (0) | 2022.05.15 |