JPA 에서 Collection 을 업데이트 할 때, 다음과 같은 에러를 받았다.
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23505, SQLState: 23505
o.h.engine.jdbc.spi.SqlExceptionHelper : Unique index or primary key violation: "PUBLIC.UK_9NEY9DAVBULF79NMN9VG6K7TN_INDEX_2 ON PUBLIC.LINE(NAME) VALUES 2"; SQL statement:
update line set created_date=?, modified_date=?, color=?, name=? where id=? [23505-200]
받았던 이유는 line entity 의 name 이 unique 하기 때문이다.
@Entity
public class Line extends BaseEntity {
...
@Column(unique = true)
private String name;
...
}
이제 update 하는 service 코드를 살펴보면, 다음과 같다.
public LineResponse updateById(final Long lineId, final LineRequest lineRequest) {
Line origin = lineRepository.findById(lineId)
.orElseThrow(() -> new DataIntegrityViolationException("Not Found lineId" + lineId));
Line line1 = lineRequest.toLine();
Station downStation = stationRepository.findById(lineRequest.getDownStationId()).orElseThrow(() -> new DataIntegrityViolationException("Not Fount downStationId" + lineRequest.getDownStationId()));
Station upStation = stationRepository.findById(lineRequest.getUpStationId()).orElseThrow(() -> new DataIntegrityViolationException("Not Fount downStationId" + lineRequest.getUpStationId()));
int distance = lineRequest.getDistance();
Section section = new Section(upStation, downStation, distance);
line1.addSection(section);
origin.update(line1);
origin.getSections().getValues().clear();
List<Section> values = origin.getSections().getValues();
/* addAll() 에서 에러가 발생했던 이유는 line1.getSections()에서 insert 가 발생한다. */
List<Section> values2 = line1.getSections().getValues();
values.addAll(values2); // line1 의 정보를 가져야 한다. 그래서 JPA 에서는 origin line 과 같이 insert 를 하려고 한다.
List<Station> stations = origin.getStations();
return LineResponse.of(origin, stations);
}
코드를 잘 살펴보면, 에러가 나는 이유를 쉽게 파악하기 힘들었다. line1 이라는 아직 ID를 부여받지 않은 Line Entity 의 부분적인 값을 업데이트 해줄 것이라 예상했지만, 실제로 JPA 의 매직은 line1에 대한 Persist 를 자동으로 만든다.
Hibernate:
insert
into
line
(id, created_date, modified_date, color, name)
values
(null, ?, ?, ?, ?)
Hibernate:
insert
into
section
(id, created_date, modified_date, distance, down_station_id, line_id, up_station_id)
values
(null, ?, ?, ?, ?, ?, ?)
Hibernate:
update
line
set
created_date=?,
modified_date=?,
color=?,
name=?
where
id=?
왜 업데이트를 하는데, Insert 구문이 왜 나가는지, 쉽사리 알아차리기 힘들었는데 JPA에서 자동으로 Entity 를 Persist 하는 바람에 발생했다.
addAll() 로 업데이트 하는 것이 아니라 아래와 같이 add() 하면 문제가 발생하지 않는다.
List<Section> values = origin.getSections().getValues();
values.add(new Section(downStation,upStation, distance));
'Spring 이해하기' 카테고리의 다른 글
[JPA] JoinColumn vs mappedBy (0) | 2021.06.13 |
---|---|
인터페이스 빈 주입을 사용해야 하는 이유 (1) | 2021.06.12 |
Spring Data JDBC 가볍게 살펴보기 - 1 (0) | 2021.05.09 |
Gradlew Command 살펴보기 (0) | 2021.01.27 |
Gradle 버전 변경하기 (1) | 2021.01.27 |
댓글