1. 이전 포스팅
https://growingsaja.tistory.com/974
2. 목표
- 추가로 data class를 선언해, 더 많은 User 데이터를 저장하고 각 기능에 필요한 entity를 추가로 더 만들어 가져다 쓸 수 있도록 개선합니다.
-> 필자의 경우, last Modified, created at 정보를 추가했고 + 데이터 조회에 쓰이는 entity 외에도 유저 정보 수정에 쓰이는 entity 작성
3. data class 수정
기존 User data class에 값 추가
신규로 UpdateUserInfo data class 추가
// vim entities/User.kt
package com.example.practicekopring.entities
import org.springframework.data.annotation.Id
import org.springframework.data.mongodb.core.mapping.Document
import java.time.LocalDateTime
@Document(collection = "users")
data class User(
@Id
val id: String? = null,
var username: String? = null,
var email: String? = null,
var lastModifiedAt_KST: String? = null, // 데이터 최종 편집 일시 추가
var lastModifiedAt: LocalDateTime? = null,
var createdAt_KST: String? = null, // 데이터 초기 생성 일시 추가
var createdAt: LocalDateTime? = null
)
data class UpdateUserInfo(
val id: String? = null,
val username: String? = null,
val email: String? = null
)
4. 소스코드 수정
// vim services/UserService.kt
package com.example.practicekopring.services
import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.repositories.UserRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId
@Service
class UserService(private val userRepository: UserRepository) {
// ...
// 5-1. 사용자 업데이트
fun updateUserWithBody(user: UpdateUserInfo): User? {
val existingUser = userRepository.findById(user.id ?: "")
val userToUpdate = existingUser.get()
userToUpdate.username = user.username ?: userToUpdate.username
userToUpdate.email = user.email ?: userToUpdate.email
// 작업 일시 저장
val currentTime = LocalDateTime.now()
userToUpdate.lastModifiedAt = currentTime
// 한국 일시 string 저장
userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ") // 데이터 최종 편집 일시 설정 // 데이터 최종 편집 일시 설정
return userRepository.save(userToUpdate)
}
// ...
// vim controllers/UserController.kt
package com.example.practicekopring.controllers
import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.services.UserService
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.PathVariable
import java.time.LocalDateTime
@RestController
@RequestMapping("/api/v1/users")
class UserController(private val userService: UserService) {
// ...
// 5-1. 사용자 업데이트 body 버전
@PostMapping("/update-with-body")
fun updateUserWithBody(
@RequestBody user: UpdateUserInfo
): User? {
val updatedUser = userService.updateUserWithBody(user)
return updatedUser
}
// ...
5. 결과 확인
6. 전체 소스코드 참고
// vim repositories/UserRepository.kt
package com.example.practicekopring.repositories
import com.example.practicekopring.entities.User
import org.springframework.data.mongodb.repository.MongoRepository
// UserRepository 인터페이스는 User 엔터티와 관련된 데이터베이스 작업을 위한 Repository입니다.
interface UserRepository : MongoRepository<User, String> {
fun findByUsername(username: String): User?
fun findByEmail(email: String): User?
fun findByUsernameContaining(keyword: String): List<User>
fun findByEmailContaining(keyword: String): List<User>
fun findAllByOrderByUsernameAsc(): List<User>
}
// vim services/UserService.kt
package com.example.practicekopring.services
import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.repositories.UserRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import java.time.LocalDateTime
import java.time.ZoneId
@Service
class UserService(private val userRepository: UserRepository) {
// 1. 모든 사용자 조회
fun getAllUsers(): List<User> {
return userRepository.findAll()
}
fun createUser(username: String, email: String): User {
val user = User(username = username, email = email)
// 현재 일시 instant로 저장
val currentTime = LocalDateTime.now()
user.createdAt = currentTime
// 한국 시간으로 변경해서 저장
user.createdAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ") // 데이터 최종 편집 일시 설정
return userRepository.save(user)
}
fun getUserByUsername(username: String): User? {
return userRepository.findByUsername(username)
}
// 3. 사용자 이메일로 조회
fun getUserByEmail(email: String): User? {
return userRepository.findByEmail(email)
}
// 5. 사용자 업데이트
fun updateUser(id: String, username: String, email: String): User? {
val existingUser = userRepository.findById(id)
if (existingUser.isPresent) {
val userToUpdate = existingUser.get()
userToUpdate.username = username
userToUpdate.email = email
// 작업 일시 저장
val currentTime = LocalDateTime.now()
userToUpdate.lastModifiedAt = currentTime
// 한국 일시 저장
userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ") // 데이터 최종 편집 일시 설정
return userRepository.save(userToUpdate)
}
return null
}
// 5-1. 사용자 업데이트
fun updateUserWithBody(user: UpdateUserInfo): User? {
val existingUser = userRepository.findById(user.id ?: "")
val userToUpdate = existingUser.get()
userToUpdate.username = user.username ?: userToUpdate.username
userToUpdate.email = user.email ?: userToUpdate.email
// 작업 일시 저장
val currentTime = LocalDateTime.now()
userToUpdate.lastModifiedAt = currentTime
// 한국 일시 string 저장
userToUpdate.lastModifiedAt_KST = currentTime.atZone(ZoneId.of("Asia/Seoul")).toString().substring(0, 19).replace("T", " ") // 데이터 최종 편집 일시 설정 // 데이터 최종 편집 일시 설정
return userRepository.save(userToUpdate)
}
// 6. 사용자 삭제
fun deleteUser(id: String) {
userRepository.deleteById(id)
}
// 7. 사용자 카운트 조회
fun getUserCount(): Long {
return userRepository.count()
}
// 8. 사용자 이름으로 부분 일치 검색
fun searchUsersByUsername(keyword: String): List<User> {
return userRepository.findByUsernameContaining(keyword)
}
// 9. 사용자 이메일로 부분 일치 검색
fun searchUsersByEmail(keyword: String): List<User> {
return userRepository.findByEmailContaining(keyword)
}
// 10. 사용자 정렬 조회 (예: 이름 오름차순)
fun getUsersSortedByName(): List<User> {
return userRepository.findAllByOrderByUsernameAsc()
}
// 11. 특정 페이지의 사용자 조회 (페이징)
fun getUsersByPage(page: Int, size: Int): Page<User> {
val pageable: Pageable = PageRequest.of(page, size)
return userRepository.findAll(pageable)
}
}
// vim controllers/UserController.kt
package com.example.practicekopring.controllers
import com.example.practicekopring.entities.User
import com.example.practicekopring.entities.UpdateUserInfo
import com.example.practicekopring.services.UserService
import org.springframework.data.domain.Page
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.PathVariable
import java.time.LocalDateTime
@RestController
@RequestMapping("/api/v1/users")
class UserController(private val userService: UserService) {
// 1. 모든 사용자 조회
@GetMapping("/")
fun getAllUsers(): List<User> {
return userService.getAllUsers()
}
// 2. 사용자 생성
@PostMapping("/create")
fun createUser(
@RequestParam username: String,
@RequestParam email: String
): User {
return userService.createUser(username, email)
}
// 3. 사용자 이름으로 조회
@GetMapping("/by-username")
fun getUserByUsername(
@RequestParam username: String
): User? {
return userService.getUserByUsername(username)
}
// 4. 사용자 이메일로 조회
@GetMapping("/by-email")
fun getUserByEmail(
@RequestParam email: String
): User? {
return userService.getUserByEmail(email)
}
// 5. 사용자 업데이트
@PutMapping("/{id}/update")
fun updateUser(
@PathVariable id: String,
@RequestParam email: String,
@RequestParam username: String
): User? {
val updatedUser = userService.updateUser(id, username, email)
return updatedUser
}
// 5-1. 사용자 업데이트 body 버전
@PostMapping("/update-with-body")
fun updateUserWithBody(
@RequestBody user: UpdateUserInfo
): User? {
val updatedUser = userService.updateUserWithBody(user)
return updatedUser
}
// 6. 사용자 삭제
@DeleteMapping("/{id}/delete")
fun deleteUser(
@PathVariable id: String
) {
userService.deleteUser(id)
}
// 7. 사용자 카운트 조회
@GetMapping("/count")
fun getUserCount(): Long {
return userService.getUserCount()
}
// 8. 사용자 이름으로 부분 일치 검색
@GetMapping("/search-by-username")
fun searchUsersByUsername(
@RequestParam keyword: String
): List<User> {
return userService.searchUsersByUsername(keyword)
}
// 9. 사용자 이메일로 부분 일치 검색
@GetMapping("/search-by-email")
fun searchUsersByEmail(
@RequestParam keyword: String
): List<User> {
return userService.searchUsersByEmail(keyword)
}
// 10. 사용자 정렬 조회 (예: 이름 오름차순)
@GetMapping("/sorted")
fun getUsersSortedByName(): List<User> {
return userService.getUsersSortedByName()
}
// 11. 특정 페이지의 사용자 조회 (페이징)
@GetMapping("/paged")
fun getUsersByPage(
@RequestParam page: Int,
@RequestParam size: Int
): Page<User> {
return userService.getUsersByPage(page, size)
}
}