[Spring] Jpa 수정(update) 시 외래 키 관리의 복잡성 해결과정

디하·2024년 3월 21일
0

bucket📦

목록 보기
2/10
post-thumbnail

Jpa 수정(update) 시외래 키 관리의 복잡성 해결과정


1. 문제 상황

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() 메서드 결과가 사용되어 외래 키 값이 아닌 다른 값이 전달될 수 있다고 한다

2. 문제 해결

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의 외래 키만을 특정하여 수정해주면 그동안 수정이 안되던 문제도 해결이 되었다

수정할 때 외래키는 따로 수정해주는 방법을 사용해서 복잡성을 빠져나올 수 있다는 것을 기억해야한다!

profile
🖥️ ⌨️🖱️🩵

0개의 댓글

관련 채용 정보