요렇게 2개의 Entity가 있다고 생각했을 때..
@Entity
@Table(name = "album")
class Album(
id: Long = 0,
name: String,
) : AuditingEntity(id) {
@Column(name = "name")
var name: String = name
protected set
@JsonBackReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "album", orphanRemoval = true, cascade = [CascadeType.ALL])
var artistAlbums: MutableList<ArtistAlbum> = mutableListOf()
}
@Entity
@Table(name = "artist_album")
class ArtistAlbum(
id:Long = 0,
artist: Artist? = null,
album: Album? = null
) : AuditingEntity(id) {
@ManyToOne(fetch = FetchType.LAZY)
@JsonManagedReference
@JoinColumn(name = "artist_id")
var artist: Artist? = artist
protected set
@ManyToOne(fetch = FetchType.LAZY)
@JsonManagedReference
@JoinColumn(name = "album_id")
var album: Album? = album
protected set
}
수정 API 작업 중.. ArtistAlbum collection 일괄업데이트 로직 상 기존 item 중 수정할 부분만 수정하고, 추가된 item이나 삭제된 item은 별도로 다루는 로직을 만들수 있는 방법이 없나.. 고민했지만.. 잘 떠오르지 않았다.
그래서 걍 속 편하게 싹 다 지우고 다시 추가하는 방향으로 잡았다.
data class AlbumUpdateReq(
@field:Positive(message = "require albumId positive")
val id: Long,
val name: String?,
val artistIds: MutableList<Long> = mutableListOf(),
){
fun createNewArtistAlbums(artists: List<Artist>): List<ArtistAlbum> {
return artists.map {
ArtistAlbum(
artist = it,
)
}
}
}
Dto를 위와 같이 만들고,
@Entity
@Table(name = "album")
class Album(
id: Long = 0,
name: String,
) : AuditingEntity(id) {
@Column(name = "name")
var name: String = name
protected set
@JsonBackReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "album", orphanRemoval = true, cascade = [CascadeType.ALL])
var artistAlbums: MutableList<ArtistAlbum> = mutableListOf()
fun update(dto: AlbumUpdateReq, newArtistAlbums: List<ArtistAlbum>): Album {
this.name = dto.name ?: this.name
//if (StringUtils.hasLength(newImgUrl)) {
// this.imgUrl = newImgUrl
//}
// 그냥 속 편하게 다 지우고, 다시 집어넣겠다.. 그냥 for문을 돌리면 ConcurrentModificationException..
for (artistAlbum in this.artistAlbums.stream().collect(Collectors.toList())) {
artistAlbum.remove()
}
for (newArtistAlbum in newArtistAlbums) {
addArtistAlbum(newArtistAlbum)
}
return this
}
private fun addArtistAlbum(artistAlbum: ArtistAlbum){
artistAlbum.addAlbum(this)
this.artistAlbums.add(artistAlbum)
}
}
@Entity
@Table(name = "artist_album")
class ArtistAlbum(
id:Long = 0,
artist: Artist? = null,
album: Album? = null
) : AuditingEntity(id) {
@ManyToOne(fetch = FetchType.LAZY)
@JsonManagedReference
@JoinColumn(name = "artist_id")
var artist: Artist? = artist
protected set
@ManyToOne(fetch = FetchType.LAZY)
@JsonManagedReference
@JoinColumn(name = "album_id")
var album: Album? = album
protected set
fun remove(){
this.album?.artistAlbums?.remove(this)
this.artist?.artistAlbums?.remove(this)
this.artist = null
this.album = null
}
fun addAlbum(album: Album){
this.album = album
}
}
서비스를 만들어줬다..
@Transactional
fun updateAlbum(dto: AlbumUpdateReq ): AlbumRes {
val artists = musicDataRepository.findArtistByIds(dto.artistIds)
val newArtistAlbums = dto.createNewArtistAlbums(artists)
val album = musicDataRepository.findAlbumById(dto.id) ?: throw AlbumNotFoundException(dto.id)
return album.update(dto, newArtistAlbums, albumImgUrl).toDto()
}
내가 원하는 방식은 아니지만.. 돌아가긴 돌아간다..