GitBucket
4.23.0
Toggle navigation
Sign in
Files
Branches
1
Releases
Issues
Pull requests
Labels
Priorities
Milestones
Wiki
Forks
yhornisse
/
bremer
Browse code
fix a bug
master
1 parent
825c242
commit
e7cb67e899e99581e4064468453cebc23b07500d
yhornisse
authored
on 19 Sep 2023
Patch
Showing
2 changed files
src/main/kotlin/dao/AlbumDao.kt
src/main/kotlin/service/AudioService.kt
Ignore Space
Show notes
View
src/main/kotlin/dao/AlbumDao.kt
/* * Copyright (c) 2023. yo-saito. All Rights Reserved. */ package net.piedpiper.bremer.dao import net.piedpiper.bremer.entity.AlbumEntity import net.piedpiper.bremer.utils.DaoUtils import net.piedpiper.bremer.utils.SelectSQLBuilder import net.piedpiper.bremer.utils.WHERE_LIKES import org.apache.ibatis.annotations.* import org.springframework.stereotype.Repository @Repository("bremer.dao.AlbumDao") @Mapper interface AlbumDao { @ResultMap("net.piedpiper.bremer.AlbumEntity") @Select("SELECT * FROM album WHERE id = #{id} FOR UPDATE") fun findOneByIdWithLock(@Param("id") id: Long): AlbumEntity? @ResultMap("net.piedpiper.bremer.AlbumEntity") @Select("SELECT * FROM album WHERE artist_id = #{artistId} AND name = #{name}") fun findOneByArtistIdAndName( @Param("artistId") artistId: Long, @Param("name") name: String ): AlbumEntity? @ResultMap("net.piedpiper.bremer.AlbumEntity") @Select( """<script> SELECT * FROM album WHERE artist_id IN <foreach item="artistId" collection="artistIds" open="(" separator="," close=")"> #{artistId} </foreach> LIMIT #{limit} </script>""" ) fun findAllByArtistIdInLimit( @Param("artistIds") artistIds: List<Long>, @Param("limit") limit: Int ): List<AlbumEntity> @ResultMap("net.piedpiper.bremer.AlbumEntity") @SelectProvider(type = Sql::class, method = "findAllByNamesLikeLimit") fun findAllByNamesLikeLimit( @Param("namesLike") namesLike: List<String>, @Param("limit") limit: Int ): List<AlbumEntity> @UpdateProvider(type = Sql::class, method = "updateOne") fun updateOne(@Param("entity") entity: AlbumEntity) @Delete("DELETE FROM album WHERE id = #{id}") fun deleteOneById(@Param("id") id: Long): Boolean class Sql { companion object { @JvmStatic fun updateOne(@Param("entity") entity: AlbumEntity): String = DaoUtils.updateOne(entity) @JvmStatic fun findAllByNamesLikeLimit( @Param("namesLike") namesLike: List<String>, ): String = SelectSQLBuilder(AlbumEntity::class) .toSql() .WHERE_LIKES("name", "namesLike", namesLike.size) .LIMIT("#{limit}") .toString() } } }
/* * Copyright (c) 2023. yo-saito. All Rights Reserved. */ package net.piedpiper.bremer.dao import net.piedpiper.bremer.entity.AlbumEntity import net.piedpiper.bremer.utils.DaoUtils import net.piedpiper.bremer.utils.SelectSQLBuilder import net.piedpiper.bremer.utils.WHERE_LIKES import org.apache.ibatis.annotations.* import org.springframework.stereotype.Repository @Repository("bremer.dao.AlbumDao") @Mapper interface AlbumDao { @ResultMap("net.piedpiper.bremer.AlbumEntity") @Select("SELECT * FROM album WHERE id = #{id} FOR UPDATE") fun findOneByIdWithLock(@Param("id") id: Long): AlbumEntity? @ResultMap("net.piedpiper.bremer.AlbumEntity") @Select( """<script> SELECT * FROM album WHERE artist_id IN <foreach item="artistId" collection="artistIds" open="(" separator="," close=")"> #{artistId} </foreach> LIMIT #{limit} </script>""" ) fun findAllByArtistIdInLimit( @Param("artistIds") artistIds: List<Long>, @Param("limit") limit: Int ): List<AlbumEntity> @ResultMap("net.piedpiper.bremer.AlbumEntity") @SelectProvider(type = Sql::class, method = "findAllByNamesLikeLimit") fun findAllByNamesLikeLimit( @Param("namesLike") namesLike: List<String>, @Param("limit") limit: Int ): List<AlbumEntity> @UpdateProvider(type = Sql::class, method = "updateOne") fun updateOne(@Param("entity") entity: AlbumEntity) @Delete("DELETE FROM album WHERE id = #{id}") fun deleteOneById(@Param("id") id: Long): Boolean class Sql { companion object { @JvmStatic fun updateOne(@Param("entity") entity: AlbumEntity): String = DaoUtils.updateOne(entity) @JvmStatic fun findAllByNamesLikeLimit( @Param("namesLike") namesLike: List<String>, ): String = SelectSQLBuilder(AlbumEntity::class) .toSql() .WHERE_LIKES("name", "namesLike", namesLike.size) .LIMIT("#{limit}") .toString() } } }
Ignore Space
Show notes
View
src/main/kotlin/service/AudioService.kt
/* * Copyright (c) 2023. yo-saito. All Rights Reserved. */ package net.piedpiper.bremer.service import net.piedpiper.bremer.dao.* import net.piedpiper.bremer.entity.AudioEntity import net.piedpiper.bremer.entity.AudioPlayHistoryEntity import net.piedpiper.bremer.exception.NotFoundException import net.piedpiper.bremer.model.api.AudioListResponse import net.piedpiper.bremer.model.api.AudioRequest import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.io.File import java.time.LocalDateTime import java.time.ZoneId @Service("bremer.service.AudioService") class AudioService( @Qualifier("bremer.dao.AudioDao") private val audioDao: AudioDao, @Qualifier("bremer.dao.ArtistDao") private val artistDao: ArtistDao, @Qualifier("bremer.dao.AlbumDao") private val albumDao: AlbumDao, @Qualifier("bremer.dao.AudioPlayHistoryDao") private val audioPlayHistoryDao: AudioPlayHistoryDao, @Qualifier("bremer.dao.TagDao") private val tagDao: TagDao ) { /** 音楽ファイル取得 */ @Transactional fun getAudioFile(slug: String): File { val audio = audioDao.findOneBySlug(slug) ?: throw NotFoundException() val file = File(audio.path) if (!file.exists()) { throw NotFoundException() } return file } /** キーワード検索 */ @Transactional fun getByKeywords( audioNamesLike: List<String>?, artistNamesLike: List<String>?, albumNamesLike: List<String>?, tagNamesLike: List<String>?, pageSize: Int ): AudioListResponse { val set = mutableSetOf<AudioEntity>() if (audioNamesLike?.isNotEmpty() == true) { set.addAll(audioDao.findAllByNameLikesLimit(audioNamesLike, pageSize)) } if (artistNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByArtistNamesLikesLimit(artistNamesLike, pageSize)) } if (albumNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByAlbumNamesLikeLimit(albumNamesLike, pageSize)) } if (tagNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByTagNamesLikeLimit(tagNamesLike, pageSize)) } return AudioListResponse( set.sortedWith(compareBy({ it.albumId }, { it.sequence })) .take(pageSize) .toList() ) } /** 最近再生した曲一覧を取得 */ @Transactional fun getLeastRecentlyAccessedAudio(pageSize: Int): AudioListResponse { val historyMap = audioPlayHistoryDao.findAllOrderLastPlayedAtDescLimit(pageSize, 0L) .associateBy { it.audioId } return if (historyMap.isNotEmpty()) audioDao.findAllByIdIn(historyMap.keys.map { it }) .sortedByDescending { historyMap[it.id]?.lastPlayedAt ?: LocalDateTime.MIN }.let { AudioListResponse(it) } else AudioListResponse() } /** 更新 */ @Transactional fun update(slug: String, request: AudioRequest) = audioDao.findOneBySlugWithLock(slug) ?.let { request.name?.apply { it.name = request.name audioDao.updateOne(it) } albumDao.findOneByIdWithLock(it.albumId)?.let { album -> request.album?.apply { albumDao.findOneByArtistIdAndName(album.artistId, request.album) ?.let { registeredAlbum -> it.albumId = registeredAlbum.id audioDao.updateOne(it) } ?: kotlin.run { album.name = request.album albumDao.updateOne(album) } } request.artist?.apply { artistDao.findOneByIdWithLock(album.artistId)?.let { artist -> artist.name = request.artist artistDao.updateOne(artist) } } } } ?: throw NotFoundException() /** 音楽削除 */ @Transactional fun delete(slug: String) = audioDao.findOneBySlugWithLock(slug) ?.let { audioDao.deleteOneBySlug(it.slug) if (audioDao.findAllByAlbumIdIn(listOf(it.albumId)) .isEmpty() ) { albumDao.deleteOneById(it.albumId); } } ?: throw NotFoundException() /** 履歴更新 */ @Transactional fun updateHistory(slug: String, pageSize: Int) { audioDao.findOneBySlug(slug)?.let { it -> audioPlayHistoryDao.insertOrUpdateOne( AudioPlayHistoryEntity( audioId = it.id, lastPlayedAt = LocalDateTime.now(ZoneId.of("Asia/Tokyo")) ) ) while (true) { audioPlayHistoryDao.findAllOrderLastPlayedAtDescLimit(pageSize, pageSize.toLong()) ?.let { result -> if (result.isEmpty()) { return } audioPlayHistoryDao.deleteAllByIds(result.map { history -> history.id }) } } } } private fun findAllByArtistNamesLikesLimit( artistNameLikes: List<String>, limit: Int ): List<AudioEntity> { val artists = artistDao.findAllByNamesLikeLimit(artistNameLikes, limit) if (artists.isEmpty()) { return emptyList() } val albums = albumDao.findAllByArtistIdInLimit(artists.map { it.id }.distinct(), limit) if (albums.isEmpty()) { return emptyList() } return audioDao.findAllByAlbumIdIn(albums.map { it.id }.distinct()) } private fun findAllByAlbumNamesLikeLimit( albumNamesLike: List<String>, limit: Int ): List<AudioEntity> { val albums = albumDao.findAllByNamesLikeLimit(albumNamesLike, limit) return if (albums.isNotEmpty()) audioDao .findAllByAlbumIdIn(albums.map { it.id }) else emptyList() } private fun findAllByTagNamesLikeLimit( tagNamesLike: List<String>, limit: Int ): List<AudioEntity> { val tags = tagDao.findAllByNamesLikeLimit(tagNamesLike, limit) return if (tags.isNotEmpty()) audioDao.findAllByTagIdIn(tags.map { it.id }) else emptyList() } }
/* * Copyright (c) 2023. yo-saito. All Rights Reserved. */ package net.piedpiper.bremer.service import net.piedpiper.bremer.dao.* import net.piedpiper.bremer.entity.AudioEntity import net.piedpiper.bremer.entity.AudioPlayHistoryEntity import net.piedpiper.bremer.exception.NotFoundException import net.piedpiper.bremer.model.api.AudioListResponse import net.piedpiper.bremer.model.api.AudioRequest import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.io.File import java.time.LocalDateTime import java.time.ZoneId @Service("bremer.service.AudioService") class AudioService( @Qualifier("bremer.dao.AudioDao") private val audioDao: AudioDao, @Qualifier("bremer.dao.ArtistDao") private val artistDao: ArtistDao, @Qualifier("bremer.dao.AlbumDao") private val albumDao: AlbumDao, @Qualifier("bremer.dao.AudioPlayHistoryDao") private val audioPlayHistoryDao: AudioPlayHistoryDao, @Qualifier("bremer.dao.TagDao") private val tagDao: TagDao ) { /** 音楽ファイル取得 */ @Transactional fun getAudioFile(slug: String): File { val audio = audioDao.findOneBySlug(slug) ?: throw NotFoundException() val file = File(audio.path) if (!file.exists()) { throw NotFoundException() } return file } /** キーワード検索 */ @Transactional fun getByKeywords( audioNamesLike: List<String>?, artistNamesLike: List<String>?, albumNamesLike: List<String>?, tagNamesLike: List<String>?, pageSize: Int ): AudioListResponse { val set = mutableSetOf<AudioEntity>() if (audioNamesLike?.isNotEmpty() == true) { set.addAll(audioDao.findAllByNameLikesLimit(audioNamesLike, pageSize)) } if (artistNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByArtistNamesLikesLimit(artistNamesLike, pageSize)) } if (albumNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByAlbumNamesLikeLimit(albumNamesLike, pageSize)) } if (tagNamesLike?.isNotEmpty() == true && set.size <= pageSize) { set.addAll(findAllByTagNamesLikeLimit(tagNamesLike, pageSize)) } return AudioListResponse( set.sortedWith(compareBy({ it.albumId }, { it.sequence })) .take(pageSize) .toList() ) } /** 最近再生した曲一覧を取得 */ @Transactional fun getLeastRecentlyAccessedAudio(pageSize: Int): AudioListResponse { val historyMap = audioPlayHistoryDao.findAllOrderLastPlayedAtDescLimit(pageSize, 0L) .associateBy { it.audioId } return if (historyMap.isNotEmpty()) audioDao.findAllByIdIn(historyMap.keys.map { it }) .sortedByDescending { historyMap[it.id]?.lastPlayedAt ?: LocalDateTime.MIN }.let { AudioListResponse(it) } else AudioListResponse() } /** 更新 */ @Transactional fun update(slug: String, request: AudioRequest) = audioDao.findOneBySlugWithLock(slug) ?.let { request.name?.apply { it.name = request.name audioDao.updateOne(it) } albumDao.findOneByIdWithLock(it.albumId)?.let { album -> request.album?.apply { album.name = request.album albumDao.updateOne(album) } request.artist?.apply { artistDao.findOneByIdWithLock(album.artistId)?.let { artist -> artist.name = request.artist artistDao.updateOne(artist) } } } } ?: throw NotFoundException() /** 音楽削除 */ @Transactional fun delete(slug: String) = audioDao.findOneBySlugWithLock(slug) ?.let { audioDao.deleteOneBySlug(it.slug) if (audioDao.findAllByAlbumIdIn(listOf(it.albumId)) .isEmpty() ) { albumDao.deleteOneById(it.albumId); } } ?: throw NotFoundException() /** 履歴更新 */ @Transactional fun updateHistory(slug: String, pageSize: Int) { audioDao.findOneBySlug(slug)?.let { it -> audioPlayHistoryDao.insertOrUpdateOne( AudioPlayHistoryEntity( audioId = it.id, lastPlayedAt = LocalDateTime.now(ZoneId.of("Asia/Tokyo")) ) ) while (true) { audioPlayHistoryDao.findAllOrderLastPlayedAtDescLimit(pageSize, pageSize.toLong()) ?.let { result -> if (result.isEmpty()) { return } audioPlayHistoryDao.deleteAllByIds(result.map { history -> history.id }) } } } } private fun findAllByArtistNamesLikesLimit( artistNameLikes: List<String>, limit: Int ): List<AudioEntity> { val artists = artistDao.findAllByNamesLikeLimit(artistNameLikes, limit) if (artists.isEmpty()) { return emptyList() } val albums = albumDao.findAllByArtistIdInLimit(artists.map { it.id }.distinct(), limit) if (albums.isEmpty()) { return emptyList() } return audioDao.findAllByAlbumIdIn(albums.map { it.id }.distinct()) } private fun findAllByAlbumNamesLikeLimit( albumNamesLike: List<String>, limit: Int ): List<AudioEntity> { val albums = albumDao.findAllByNamesLikeLimit(albumNamesLike, limit) return if (albums.isNotEmpty()) audioDao .findAllByAlbumIdIn(albums.map { it.id }) else emptyList() } private fun findAllByTagNamesLikeLimit( tagNamesLike: List<String>, limit: Int ): List<AudioEntity> { val tags = tagDao.findAllByNamesLikeLimit(tagNamesLike, limit) return if (tags.isNotEmpty()) audioDao.findAllByTagIdIn(tags.map { it.id }) else emptyList() } }
Show line notes below