fix(osiv): lazy 관계 선로딩을 보완한다
This commit is contained in:
@@ -74,6 +74,28 @@ interface ChatCharacterRepository : JpaRepository<ChatCharacter, Long> {
|
||||
pageable: Pageable
|
||||
): List<ChatCharacter>
|
||||
|
||||
/**
|
||||
* 특정 캐릭터와 태그를 공유하는 다른 캐릭터 ID를 무작위로 조회 (현재 캐릭터 제외)
|
||||
*/
|
||||
@Query(
|
||||
"""
|
||||
SELECT c.id FROM ChatCharacter c
|
||||
JOIN c.tagMappings tm
|
||||
JOIN tm.tag t
|
||||
WHERE c.isActive = true
|
||||
AND c.id <> :characterId
|
||||
AND t.id IN (
|
||||
SELECT t2.id FROM ChatCharacterTagMapping tm2 JOIN tm2.tag t2 WHERE tm2.chatCharacter.id = :characterId
|
||||
)
|
||||
GROUP BY c.id
|
||||
ORDER BY function('RAND')
|
||||
"""
|
||||
)
|
||||
fun findRandomIdsBySharedTags(
|
||||
@Param("characterId") characterId: Long,
|
||||
pageable: Pageable
|
||||
): List<Long>
|
||||
|
||||
/**
|
||||
* 활성 캐릭터 무작위 조회
|
||||
*/
|
||||
@@ -99,6 +121,27 @@ interface ChatCharacterRepository : JpaRepository<ChatCharacter, Long> {
|
||||
fun findRandomActiveExcluding(@Param("excludeIds") excludeIds: List<Long>, pageable: Pageable): List<ChatCharacter>
|
||||
|
||||
fun findByIdInAndIsActiveTrue(ids: List<Long>): List<ChatCharacter>
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT DISTINCT c FROM ChatCharacter c
|
||||
LEFT JOIN FETCH c.tagMappings tm
|
||||
LEFT JOIN FETCH tm.tag
|
||||
WHERE c.id = :id
|
||||
"""
|
||||
)
|
||||
fun findByIdWithTagMappings(@Param("id") id: Long): ChatCharacter?
|
||||
|
||||
@Query(
|
||||
"""
|
||||
SELECT DISTINCT c FROM ChatCharacter c
|
||||
LEFT JOIN FETCH c.tagMappings tm
|
||||
LEFT JOIN FETCH tm.tag
|
||||
WHERE c.id IN :ids
|
||||
"""
|
||||
)
|
||||
fun findByIdInWithTagMappings(@Param("ids") ids: List<Long>): List<ChatCharacter>
|
||||
|
||||
fun findByCreatorMemberId(creatorMemberId: Long): ChatCharacter?
|
||||
fun existsByCreatorMemberId(creatorMemberId: Long): Boolean
|
||||
}
|
||||
|
||||
@@ -210,13 +210,15 @@ class ChatCharacterService(
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
fun getOtherCharactersBySharedTags(characterId: Long, limit: Int = 10): List<ChatCharacter> {
|
||||
val others = chatCharacterRepository.findRandomBySharedTags(
|
||||
val ids = chatCharacterRepository.findRandomIdsBySharedTags(
|
||||
characterId,
|
||||
PageRequest.of(0, limit)
|
||||
)
|
||||
// 태그 초기화 (지연 로딩 문제 방지)
|
||||
others.forEach { it.tagMappings.size }
|
||||
return others
|
||||
).distinct()
|
||||
if (ids.isEmpty()) return emptyList()
|
||||
|
||||
val charactersById = chatCharacterRepository.findByIdInWithTagMappings(ids)
|
||||
.associateBy { it.id }
|
||||
return ids.mapNotNull { charactersById[it] }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,13 +557,12 @@ class ChatCharacterService(
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
fun getCharacterDetail(id: Long): ChatCharacter? {
|
||||
val character = findById(id) ?: return null
|
||||
val character = chatCharacterRepository.findByIdWithTagMappings(id) ?: return null
|
||||
|
||||
// 지연 로딩된 관계 데이터 초기화
|
||||
character.tagMappings.size
|
||||
character.valueMappings.size
|
||||
character.hobbyMappings.size
|
||||
character.goalMappings.size
|
||||
character.valueMappings.forEach { it.value.value }
|
||||
character.hobbyMappings.forEach { it.hobby.hobby }
|
||||
character.goalMappings.forEach { it.goal.goal }
|
||||
character.memories.size
|
||||
character.personalities.size
|
||||
character.backgrounds.size
|
||||
|
||||
@@ -43,8 +43,13 @@ class OriginalWorkQueryService(
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
fun getOriginalWork(id: Long): OriginalWork {
|
||||
return originalWorkRepository.findByIdAndIsDeletedFalse(id)
|
||||
val originalWork = originalWorkRepository.findByIdAndIsDeletedFalse(id)
|
||||
.orElseThrow { SodaException(messageKey = "chat.original.not_found") }
|
||||
|
||||
originalWork.originalLinks.forEach { it.url }
|
||||
originalWork.tagMappings.forEach { it.tag.tag }
|
||||
|
||||
return originalWork
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user