parent
155ea5c5e4
commit
705459ee90
|
@ -32,6 +32,7 @@ interface AdminAudioContentQueryRepository {
|
||||||
): List<GetAdminContentListItem>
|
): List<GetAdminContentListItem>
|
||||||
|
|
||||||
fun getHashTagList(audioContentId: Long): List<String>
|
fun getHashTagList(audioContentId: Long): List<String>
|
||||||
|
fun findByIdAndActiveTrue(audioContentId: Long): AudioContent?
|
||||||
}
|
}
|
||||||
|
|
||||||
class AdminAudioContentQueryRepositoryImpl(
|
class AdminAudioContentQueryRepositoryImpl(
|
||||||
|
@ -143,6 +144,16 @@ class AdminAudioContentQueryRepositoryImpl(
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findByIdAndActiveTrue(audioContentId: Long): AudioContent? {
|
||||||
|
return queryFactory
|
||||||
|
.select(audioContent)
|
||||||
|
.where(
|
||||||
|
audioContent.id.eq(audioContentId),
|
||||||
|
audioContent.isActive.isTrue
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
|
||||||
private fun formattedDateExpression(
|
private fun formattedDateExpression(
|
||||||
dateTime: DateTimePath<LocalDateTime>,
|
dateTime: DateTimePath<LocalDateTime>,
|
||||||
format: String = "%Y-%m-%d"
|
format: String = "%Y-%m-%d"
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
data class AddItemToCurationRequest(
|
||||||
|
val curationId: Long,
|
||||||
|
val contentIdList: List<Long>
|
||||||
|
)
|
|
@ -33,4 +33,31 @@ class AdminContentCurationController(private val service: AdminContentCurationSe
|
||||||
fun getContentCurationList(
|
fun getContentCurationList(
|
||||||
@RequestParam tabId: Long
|
@RequestParam tabId: Long
|
||||||
) = ApiResponse.ok(service.getContentCurationList(tabId = tabId))
|
) = ApiResponse.ok(service.getContentCurationList(tabId = tabId))
|
||||||
|
|
||||||
|
@GetMapping("/items")
|
||||||
|
fun getCurationItems(
|
||||||
|
@RequestParam curationId: Long
|
||||||
|
) = ApiResponse.ok(service.getCurationItem(curationId = curationId))
|
||||||
|
|
||||||
|
@GetMapping("/search/content")
|
||||||
|
fun searchCurationContentItem(
|
||||||
|
@RequestParam curationId: Long,
|
||||||
|
@RequestParam searchWord: String
|
||||||
|
) = ApiResponse.ok(service.searchCurationContentItem(curationId, searchWord))
|
||||||
|
|
||||||
|
@GetMapping("/search/series")
|
||||||
|
fun searchCurationSeriesItem(
|
||||||
|
@RequestParam curationId: Long,
|
||||||
|
@RequestParam searchWord: String
|
||||||
|
) = ApiResponse.ok(service.searchCurationSeriesItem(curationId, searchWord))
|
||||||
|
|
||||||
|
@PostMapping("/add/item")
|
||||||
|
fun addItemToCuration(@RequestBody request: AddItemToCurationRequest) {
|
||||||
|
ApiResponse.ok(service.addItemToCuration(request), "큐레이션 아이템을 등록했습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/remove/item")
|
||||||
|
fun removeItemInCuration(@RequestBody request: RemoveItemInCurationRequest) {
|
||||||
|
ApiResponse.ok(service.removeItemInCuration(request), "큐레이션 아이템을 제거했습니다.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCurationItem.audioContentCurationItem
|
||||||
|
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
|
||||||
|
interface AdminContentCurationItemRepository :
|
||||||
|
JpaRepository<AudioContentCurationItem, Long>,
|
||||||
|
AdminContentCurationItemQueryRepository
|
||||||
|
|
||||||
|
interface AdminContentCurationItemQueryRepository {
|
||||||
|
fun findByCurationIdAndSeriesId(curationId: Long, seriesId: Long?): AudioContentCurationItem?
|
||||||
|
fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): AudioContentCurationItem?
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdminContentCurationItemQueryRepositoryImpl(
|
||||||
|
val queryFactory: JPAQueryFactory
|
||||||
|
) : AdminContentCurationItemQueryRepository {
|
||||||
|
override fun findByCurationIdAndSeriesId(curationId: Long, seriesId: Long?): AudioContentCurationItem? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(audioContentCurationItem)
|
||||||
|
.innerJoin(audioContentCurationItem.curation, audioContentCuration)
|
||||||
|
.innerJoin(audioContentCurationItem.series, series)
|
||||||
|
.where(
|
||||||
|
audioContentCurationItem.curation.id.eq(curationId),
|
||||||
|
audioContentCurationItem.series.id.eq(seriesId)
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findByCurationIdAndContentId(curationId: Long, contentId: Long?): AudioContentCurationItem? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(audioContentCurationItem)
|
||||||
|
.innerJoin(audioContentCurationItem.curation, audioContentCuration)
|
||||||
|
.innerJoin(audioContentCurationItem.content, audioContent)
|
||||||
|
.where(
|
||||||
|
audioContentCurationItem.curation.id.eq(curationId),
|
||||||
|
audioContentCurationItem.content.id.eq(contentId)
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,14 @@
|
||||||
package kr.co.vividnext.sodalive.admin.content.curation
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration
|
import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCuration.audioContentCuration
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.QAudioContentCurationItem.audioContentCurationItem
|
||||||
import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab
|
import kr.co.vividnext.sodalive.content.main.tab.QAudioContentMainTab.audioContentMainTab
|
||||||
|
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
|
||||||
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@ -15,11 +20,18 @@ interface AdminContentCurationRepository :
|
||||||
interface AdminContentCurationQueryRepository {
|
interface AdminContentCurationQueryRepository {
|
||||||
fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse>
|
fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse>
|
||||||
fun findByIdAndActive(id: Long): AudioContentCuration?
|
fun findByIdAndActive(id: Long): AudioContentCuration?
|
||||||
|
fun findByCurationIdAndItemId(curationId: Long, itemId: Long): AudioContentCurationItem?
|
||||||
|
fun getAudioContentCurationItemList(curationId: Long): List<GetCurationItemResponse>
|
||||||
|
fun searchCurationContentItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse>
|
||||||
|
fun searchCurationSeriesItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class AdminContentCurationQueryRepositoryImpl(
|
class AdminContentCurationQueryRepositoryImpl(
|
||||||
private val queryFactory: JPAQueryFactory
|
private val queryFactory: JPAQueryFactory,
|
||||||
|
|
||||||
|
@Value("\${cloud.aws.cloud-front.host}")
|
||||||
|
private val imageHost: String
|
||||||
) : AdminContentCurationQueryRepository {
|
) : AdminContentCurationQueryRepository {
|
||||||
override fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> {
|
override fun getAudioContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> {
|
||||||
return queryFactory
|
return queryFactory
|
||||||
|
@ -52,4 +64,89 @@ class AdminContentCurationQueryRepositoryImpl(
|
||||||
)
|
)
|
||||||
.fetchFirst()
|
.fetchFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findByCurationIdAndItemId(curationId: Long, itemId: Long): AudioContentCurationItem? {
|
||||||
|
return queryFactory.selectFrom(audioContentCurationItem)
|
||||||
|
.innerJoin(audioContentCurationItem.curation, audioContentCuration)
|
||||||
|
.where(audioContentCuration.id.eq(curationId), audioContentCurationItem.id.eq(itemId))
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAudioContentCurationItemList(curationId: Long): List<GetCurationItemResponse> {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
QGetCurationItemResponse(
|
||||||
|
audioContentCurationItem.id,
|
||||||
|
audioContent.title.coalesce(series.title),
|
||||||
|
audioContent.detail.coalesce(series.introduction),
|
||||||
|
audioContent.coverImage.coalesce(series.coverImage).prepend("/").prepend(imageHost),
|
||||||
|
audioContent.member.nickname.coalesce(series.member.nickname).coalesce(""),
|
||||||
|
audioContent.isAdult.coalesce(series.isAdult)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(audioContentCurationItem)
|
||||||
|
.innerJoin(audioContentCurationItem.curation, audioContentCuration)
|
||||||
|
.leftJoin(audioContentCurationItem.series, series)
|
||||||
|
.leftJoin(audioContentCurationItem.content, audioContent)
|
||||||
|
.where(
|
||||||
|
audioContentCuration.id.eq(curationId),
|
||||||
|
audioContentCurationItem.isActive.isTrue
|
||||||
|
)
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchCurationContentItem(
|
||||||
|
curationId: Long,
|
||||||
|
searchWord: String
|
||||||
|
): List<SearchCurationItemResponse> {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
QSearchCurationItemResponse(
|
||||||
|
audioContent.id,
|
||||||
|
audioContent.title,
|
||||||
|
audioContent.coverImage.prepend("/").prepend(imageHost)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(audioContent)
|
||||||
|
.leftJoin(audioContentCurationItem)
|
||||||
|
.on(
|
||||||
|
audioContent.id.eq(audioContentCurationItem.content.id)
|
||||||
|
.and(audioContentCurationItem.curation.id.eq(curationId))
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
audioContent.duration.isNotNull
|
||||||
|
.and(audioContent.member.isNotNull)
|
||||||
|
.and(audioContent.isActive.isTrue)
|
||||||
|
.and(audioContent.title.contains(searchWord))
|
||||||
|
.and(audioContentCurationItem.id.isNull)
|
||||||
|
)
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchCurationSeriesItem(
|
||||||
|
curationId: Long,
|
||||||
|
searchWord: String
|
||||||
|
): List<SearchCurationItemResponse> {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
QSearchCurationItemResponse(
|
||||||
|
series.id,
|
||||||
|
series.title,
|
||||||
|
series.coverImage.prepend("/").prepend(imageHost)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(series)
|
||||||
|
.leftJoin(audioContentCurationItem)
|
||||||
|
.on(
|
||||||
|
series.id.eq(audioContentCurationItem.series.id)
|
||||||
|
.and(audioContentCurationItem.curation.id.eq(curationId))
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
series.isActive.isTrue
|
||||||
|
.and(series.member.isNotNull)
|
||||||
|
.and(series.title.contains(searchWord))
|
||||||
|
.and(audioContentCurationItem.id.isNull)
|
||||||
|
)
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package kr.co.vividnext.sodalive.admin.content.curation
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.admin.content.AdminContentRepository
|
||||||
|
import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository
|
||||||
import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository
|
import kr.co.vividnext.sodalive.admin.content.tab.AdminContentMainTabRepository
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCuration
|
||||||
|
import kr.co.vividnext.sodalive.content.main.curation.AudioContentCurationItem
|
||||||
import org.springframework.data.repository.findByIdOrNull
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
@ -10,7 +13,10 @@ import org.springframework.transaction.annotation.Transactional
|
||||||
@Service
|
@Service
|
||||||
class AdminContentCurationService(
|
class AdminContentCurationService(
|
||||||
private val repository: AdminContentCurationRepository,
|
private val repository: AdminContentCurationRepository,
|
||||||
private val contentMainTabRepository: AdminContentMainTabRepository
|
private val contentMainTabRepository: AdminContentMainTabRepository,
|
||||||
|
private val seriesRepository: AdminContentSeriesRepository,
|
||||||
|
private val contentRepository: AdminContentRepository,
|
||||||
|
private val contentCurationItemRepository: AdminContentCurationItemRepository
|
||||||
) {
|
) {
|
||||||
@Transactional
|
@Transactional
|
||||||
fun createContentCuration(request: CreateContentCurationRequest) {
|
fun createContentCuration(request: CreateContentCurationRequest) {
|
||||||
|
@ -76,4 +82,65 @@ class AdminContentCurationService(
|
||||||
fun getContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> {
|
fun getContentCurationList(tabId: Long): List<GetAdminContentCurationResponse> {
|
||||||
return repository.getAudioContentCurationList(tabId = tabId)
|
return repository.getAudioContentCurationList(tabId = tabId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCurationItem(curationId: Long): List<GetCurationItemResponse> {
|
||||||
|
return repository.getAudioContentCurationItemList(curationId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchCurationContentItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> {
|
||||||
|
return repository.searchCurationContentItem(curationId, searchWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchCurationSeriesItem(curationId: Long, searchWord: String): List<SearchCurationItemResponse> {
|
||||||
|
return repository.searchCurationSeriesItem(curationId, searchWord)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun addItemToCuration(request: AddItemToCurationRequest) {
|
||||||
|
// 큐레이션 조회
|
||||||
|
val audioContentCuration = repository.findByIdOrNull(id = request.curationId)
|
||||||
|
?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
|
||||||
|
if (audioContentCuration.isSeries) {
|
||||||
|
request.contentIdList.forEach { seriesId ->
|
||||||
|
val series = seriesRepository.findByIdAndActiveTrue(seriesId)
|
||||||
|
|
||||||
|
if (series != null) {
|
||||||
|
val item = contentCurationItemRepository.findByCurationIdAndSeriesId(
|
||||||
|
curationId = request.curationId,
|
||||||
|
seriesId = series.id
|
||||||
|
) ?: AudioContentCurationItem()
|
||||||
|
item.curation = audioContentCuration
|
||||||
|
item.series = series
|
||||||
|
item.isActive = true
|
||||||
|
contentCurationItemRepository.save(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
request.contentIdList.forEach { contentId ->
|
||||||
|
val audioContent = contentRepository.findByIdAndActiveTrue(contentId)
|
||||||
|
|
||||||
|
if (audioContent != null) {
|
||||||
|
val item = contentCurationItemRepository.findByCurationIdAndContentId(
|
||||||
|
curationId = request.curationId,
|
||||||
|
contentId = audioContent.id
|
||||||
|
) ?: AudioContentCurationItem()
|
||||||
|
item.curation = audioContentCuration
|
||||||
|
item.content = audioContent
|
||||||
|
item.isActive = true
|
||||||
|
contentCurationItemRepository.save(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun removeItemInCuration(request: RemoveItemInCurationRequest) {
|
||||||
|
val audioContentCurationItem = repository.findByCurationIdAndItemId(
|
||||||
|
curationId = request.curationId,
|
||||||
|
itemId = request.itemId
|
||||||
|
)
|
||||||
|
|
||||||
|
audioContentCurationItem?.isActive = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
import com.querydsl.core.annotations.QueryProjection
|
||||||
|
|
||||||
|
data class GetCurationItemResponse @QueryProjection constructor(
|
||||||
|
val id: Long,
|
||||||
|
val title: String,
|
||||||
|
val desc: String,
|
||||||
|
val coverImageUrl: String,
|
||||||
|
val creatorNickname: String,
|
||||||
|
val isAdult: Boolean
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
data class RemoveItemInCurationRequest(
|
||||||
|
val curationId: Long,
|
||||||
|
val itemId: Long
|
||||||
|
)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.content.curation
|
||||||
|
|
||||||
|
import com.querydsl.core.annotations.QueryProjection
|
||||||
|
|
||||||
|
data class SearchCurationItemResponse @QueryProjection constructor(
|
||||||
|
val id: Long,
|
||||||
|
val title: String,
|
||||||
|
val coverImageUrl: String
|
||||||
|
)
|
|
@ -22,6 +22,7 @@ interface AdminContentSeriesQueryRepository {
|
||||||
): List<GetAdminSeriesListItem>
|
): List<GetAdminSeriesListItem>
|
||||||
|
|
||||||
fun searchSeriesList(searchWord: String): List<GetAdminSearchSeriesListItem>
|
fun searchSeriesList(searchWord: String): List<GetAdminSearchSeriesListItem>
|
||||||
|
fun findByIdAndActiveTrue(seriesId: Long): Series?
|
||||||
}
|
}
|
||||||
|
|
||||||
class AdminContentSeriesQueryRepositoryImpl(
|
class AdminContentSeriesQueryRepositoryImpl(
|
||||||
|
@ -97,4 +98,14 @@ class AdminContentSeriesQueryRepositoryImpl(
|
||||||
.orderBy(series.id.desc())
|
.orderBy(series.id.desc())
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun findByIdAndActiveTrue(seriesId: Long): Series? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(series)
|
||||||
|
.where(
|
||||||
|
series.id.eq(seriesId),
|
||||||
|
series.isActive.isTrue
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package kr.co.vividnext.sodalive.content.main.curation
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||||
|
import kr.co.vividnext.sodalive.content.AudioContent
|
||||||
|
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.FetchType
|
||||||
|
import javax.persistence.JoinColumn
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
import javax.persistence.Table
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "content_curation_item")
|
||||||
|
data class AudioContentCurationItem(
|
||||||
|
@Column(nullable = false)
|
||||||
|
var orders: Int = 1,
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
var isActive: Boolean = true
|
||||||
|
) : BaseEntity() {
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "curation_id", nullable = false)
|
||||||
|
var curation: AudioContentCuration? = null
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "content_id", nullable = true)
|
||||||
|
var content: AudioContent? = null
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "series_id", nullable = true)
|
||||||
|
var series: Series? = null
|
||||||
|
}
|
Loading…
Reference in New Issue