EntityChangeListener.kt
package com.example.templateproject.persistence.configuration
import com.example.templateproject.persistence.entity.BaseEntity
import com.example.templateproject.persistence.entity.history.BaseHistoryEntity
import com.example.templateproject.persistence.entity.history.HistoryEvent
import com.example.templateproject.persistence.entity.mapper.AbstractHistoryMapper
import com.example.templateproject.persistence.repository.history.BaseHistoryRepository
import jakarta.persistence.PrePersist
import jakarta.persistence.PreRemove
import jakarta.persistence.PreUpdate
import org.slf4j.LoggerFactory
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component
@Component
class EntityChangeListener(
private val applicationContext: ApplicationContext,
) {
companion object {
private val LOGGER = LoggerFactory.getLogger(EntityChangeListener::class.java)
private const val HISTORY_MAPPER_SUFFIX = "HistoryMapper"
private const val HISTORY_REPOSITORY_SUFFIX = "HistoryRepository"
}
@PrePersist
fun postPersist(entity: BaseEntity) = saveHistoryEntity(entity, HistoryEvent.CREATE)
@PreUpdate
fun preUpdate(entity: BaseEntity) = saveHistoryEntity(entity, HistoryEvent.UPDATE)
@PreRemove
fun preRemove(entity: BaseEntity) = saveHistoryEntity(entity, HistoryEvent.DELETE)
private fun saveHistoryEntity(
entity: BaseEntity,
event: HistoryEvent,
) {
val mapper = getHistoryMapper(entity)
val repository = getHistoryRepository(entity)
if (mapper != null && repository != null) {
val historyEntity = mapper.toHistoryEntity(entity, event)
repository.save(historyEntity)
LOGGER.debug("Created history entry for {} entity with id: {}", entity::class.simpleName, entity.id)
}
}
@Suppress("UNCHECKED_CAST")
private fun getHistoryMapper(entity: BaseEntity): AbstractHistoryMapper<BaseEntity, BaseHistoryEntity>? {
val mapperBeanName = entity::class.simpleName + HISTORY_MAPPER_SUFFIX
return applicationContext
.getBeansOfType(AbstractHistoryMapper::class.java)
.filterKeys { it.equals(mapperBeanName, ignoreCase = true) }
.values
.firstOrNull() as AbstractHistoryMapper<BaseEntity, BaseHistoryEntity>
}
@Suppress("UNCHECKED_CAST")
private fun getHistoryRepository(entity: BaseEntity): BaseHistoryRepository<BaseHistoryEntity>? {
val repositoryBeanName = entity::class.simpleName + HISTORY_REPOSITORY_SUFFIX
return applicationContext
.getBeansOfType(BaseHistoryRepository::class.java)
.filterKeys { it.equals(repositoryBeanName, ignoreCase = true) }
.values
.firstOrNull() as BaseHistoryRepository<BaseHistoryEntity>
}
}