Spring Boot와 JPA를 사용하여 개발하는 과정에서, Shop 엔티티의 정보를 업데이트하는 기능을 구현하던 중 문제가 발생했다.
분명 오류는 나지 않는데, DB에 수정된 객체로 저장되지 않았다
문제의 코드
@Getter
@NoArgsConstructor
@Entity
public class Shop extends BaseTime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "shop_id")
private Long shopId;
private String name;
private String address;
private String opentime;
private String website;
private String content;
private String phone;
@Enumerated(EnumType.STRING)
private ShopStatus status;
@Column(name = "is_deleted")
private Boolean isDeleted;
// 리뷰 개수
private int reviewCnt;
// 매장 저장 개수
private int favoriteCnt;
// 매장 별점 평균
private double rateAvg;
// 메뉴
@OneToMany(mappedBy = "shop")
private List<Menu> menuList;
// 매장이미지
@OneToMany(mappedBy = "shop")
private List<ShopImg> shopImgList;
// 사업자 증명
@OneToMany(mappedBy = "shop")
private List<CertificateImg> certificateImgList;
// 매장 저장
@OneToMany(mappedBy = "shop")
private List<Favorite> favoriteList;
// 아트판
@OneToMany(mappedBy = "shop")
private List<ArtRef> artRefList;
// 리뷰
@OneToMany(mappedBy = "shop")
private List<Review> reviewList;
// 주소(동)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dong_id")
private Dong dong;
@OneToOne(mappedBy = "shop")
private Owner owner;
public void shopUpdate (String name, String address, String opentime, String website, String content, Dong dong,String phone , ShopStatus status) {
this.name = name;
this.address = address;
this.opentime = opentime;
this.website = website;
this.content = content;
this.dong = dong;
this.phone = phone;
this.status = status;
}
shop.shopUpdate(
shopModificationRequestDto.getName(),
String.join(" ", city.getName(), districts.getName(), dong.getName(), shopModificationRequestDto.getAddress()),
shopModificationRequestDto.getOpentime(),
shopModificationRequestDto.getWebsite(),
shopModificationRequestDto.getContent(),
dong, // Dong 엔티티 직접 전달
shopModificationRequestDto.getPhone(),
shopModificationRequestDto.getStatus()
);
shop = shopRepository.save(shop);
여기서 dong 엔티티를 직접 update 객체로 넘겨서 난 오류 였다
기존 코드에서는 shop.shopUpdate() 메서드를 호출할 때 dong 객체를 직접 전달했는데, 이로 인해 외래 키 값이 올바르게 전달되지 않은 문제였다
객체를 직접 전달하면 해당 객체의 toString() 메서드 결과가 사용되어 외래 키 값이 아닌 다른 값이 전달될 수 있다고 한다
shop.shopUpdate(
shopModificationRequestDto.getName(),
String.join(" ", city.getName(), districts.getName(), dong.getName(), shopModificationRequestDto.getAddress()),
shopModificationRequestDto.getOpentime(),
shopModificationRequestDto.getWebsite(),
shopModificationRequestDto.getContent(),
shopModificationRequestDto.getPhone(),
shopModificationRequestDto.getStatus()
);
// Dong 엔티티의 외래 키만 별도로 업데이트
shopRepository.updateDongIdByShopId(dongId, shop.getShopId());
@Query("UPDATE Shop s " +
"SET s.dong.dongId = :dongId " +
"WHERE s.shopId = :shopId")
@Modifying(clearAutomatically = true)
void updateDongIdByShopId(@Param("dongId") Long dongId, @Param("shopId") Long shopId);
그래서 외래키인 dongId 는 별도로 직접 수정하는 방법을 사용했다
shopRepository.updateDongIdByShopId(dongId, shop.getShopId())를 호출하여 Dong의 외래 키만을 특정하여 수정해주면 그동안 수정이 안되던 문제도 해결이 되었다
수정할 때 외래키는 따로 수정해주는 방법을 사용해서 복잡성을 빠져나올 수 있다는 것을 기억해야한다!