반응형
좋아요 기능을 만들기 위해 아래와 같은 ERD를 구성하였고 FK 2개를 복합키로 가지는 좋아요 테이블을 생성하였다.
그 후 좋아요에 대한 삭제를 하려는데 아래와 같은 에러를 만났다. 이렇게 FK 두개를 복합키로 가지지 않고 일반적인 테이블인 경우 형타입이 안맞아서 발생하는 에러인데 나의 경우는 여기에 해당하지 않았다.
InvalidDataAccessApiUsageException: Can not set com.ownsong.api.user.entity.User field com.ownsong.api.album.entity.LikesId.user to java.lang.Long; nested exception is java.lang.IllegalArgumentException: Can not set com.ownsong.api.user.entity.User field com.ownsong.api.album.entity.LikesId.user to java.lang.Long
결론만 먼저 얘기 하면 연관관계를 끊고 삭제를 해줘야했다.
에러 발생 과정
먼저 구성은 아래와 같다 복합키를 가지는 Entity이기에 LikesId와 Likes를 만든다
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;
@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
public class LikesId implements Serializable {
private static final long serialVersionUID = 1201L;
@EqualsAndHashCode.Include
@ManyToOne
@JoinColumn(name = "USER_ID")
private User user;
@EqualsAndHashCode.Include
@ManyToOne
@JoinColumn(name = "ALBUM_ID")
private Album album;
public LikesId(User user, Album album) {
this.user = user;
this.album = album;
}
}
import com.ownsong.api.user.entity.User;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Getter
@Table(name = "LIKES")
@NoArgsConstructor
@IdClass(LikesId.class)
public class Likes {
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "USER_ID")
private User user;
@Id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ALBUM_ID")
private Album album;
@Builder
public Likes(User user, Album album) {
this.user = user;
this.album = album;
}
}
그 후 서비스단에서 아래와 같은 로직을 작성하였다.
이 때 글 초반부에 작성했던 에러가 발생했고, 며칠동안 헤맸다.
@Transactional
public void updateAlbumArticleLike(long albumId, User user){
Album album = albumRepository.findById(albumId).orElse(null);
//좋아요 가져온다음에 좋아요인지 싫어요인지에 따라 바꾸고 총 좋아요 수 업데이트
LikesId key = new LikesId(user, album);
// 키가 존재하면 삭제 후 총 좋아요 수 업데이트
if(likesRepository.findById(key).isPresent()){
Likes likes = likesRepository.findById(key).get();
//아랫줄이 해당 에러 발생부분
likesRepository.delete(likes);
album.updateNumberOfLikes(false);
}else{
Likes likes = Likes.builder()
.user(user)
.album(album)
.build();
album.getLikesList().add(likes);
album.updateNumberOfLikes(true);
}
albumRepository.save(album);
해결과정
아래와 같이 좋아요를 album과의 관계에서 끊고 likes 삭제 후 저장함으로써 문제를 해결했다.
@Transactional
public void updateAlbumArticleLike(long albumId, User user) {
Album album = albumRepository.findById(albumId).orElse(null);
// 좋아요 가져온다음에 좋아요인지 싫어요인지에 따라 바꾸고 총 좋아요 수 업뎃
LikesId key = new LikesId(user, album);
if (likesRepository.findById(key).isPresent()) {
// likes를 앨범과의 관계에서 끊고 likes 삭제 후 저장
Likes likes = likesRepository.findById(key).get();
album.getLikesList().remove(likes);
// 아래의 메소드는 JpaRepository를 상속한 LikesRepository에서 따로 생성하여야한다.
likesRepository.deleteLikesByAlbumAndUser(album, user);
album.updateNumberOfLikes(false);
} else {
Likes likes = Likes.builder()
.user(user)
.album(album)
.build();
album.getLikesList().add(likes);
album.updateNumberOfLikes(true);
}
// 총 좋아요 수 업데이트 & else 에서 관계 맺은 앨범 업데이트
albumRepository.save(album);
}
반응형
'⌨Programming > Spring' 카테고리의 다른 글
스프링에서 S3로 파일업로드하기 (0) | 2023.05.30 |
---|---|
Springboot 개발환경에서 노출되면 안되는 설정값, 환경변수 관리하기 (0) | 2023.05.12 |