커밋을 할때 인텔리제이의 터미널만이 아니라 왼쪽에서 창을 띄우고 거기에 메시지를 입력한뒤 커빗 버튼을 눌러도 된다는걸 처음 알았다.
그리고 여럿이서 협력할때는 깃허브를 생성하고서 이슈를 눌러서 거기에 각자 생성할것에 대한 체크리스트를 작성하고
@PreAuthorize("hasAuthority('USER')") 이건 유저 권한을 가진 사람만 접근가능
package com.sparta.dianomi.common.model
import jakarta.persistence.Column
import jakarta.persistence.EntityListeners
import jakarta.persistence.MappedSuperclass
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.LocalDateTime
@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class BaseTimeEntity {
@CreatedDate
@Column(nullable = false, updatable = false)
var createdAt: LocalDateTime = LocalDateTime.now()
protected set
@LastModifiedDate
@Column(nullable = false)
var updatedAt: LocalDateTime = LocalDateTime.now()
protected set
}
이걸 상속해서 entity를 만드는 법
@Entity
class Menu(
var name: String,
var description: String,
var price: Int
) {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
}
여기에
@Entity
class Menu(
var name: String,
var description: String,
var price: Int
) : BaseTimeEntity() { // BaseTimeEntity 상속
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
}
이렇게 하면 된다.
@Service
class MenuServiceImpl(
private val menuRepository: MenuRepository
): MenuService {
override fun getAllMenus(): List<MenuDto> {
return menuRepository.findAll().map { MenuDto(it) }
}
override fun getMenu(menuId: Long): MenuDto {
val menu = menuRepository.findById(menuId).orElseThrow { NoSuchElementException("Menu not found") }
return MenuDto(menu)
}
override fun createMenu(menuCreateDto: MenuCreateDto): MenuDto {
val newMenu = Menu(
name = menuCreateDto.name,
price = menuCreateDto.price,
description = menuCreateDto.description
)
menuRepository.save(newMenu)
return MenuDto(newMenu)
}
override fun deleteMenu(menuId: Long) {
menuRepository.deleteById(menuId)
}
override fun updateMenu(menuId: Long, menuUpdateDto: MenuUpdateDto): MenuDto {
val menu = menuRepository.findById(menuId).orElseThrow { NoSuchElementException("Menu not found") }
menu.name = menuUpdateDto.name
menu.price = menuUpdateDto.price
menu.description = menuUpdateDto.description
menuRepository.save(menu)
return MenuDto(menu)
}
여기에서 }MenuDto(it)의 it, MenuDto(menu)의 menu, MenuDto(newMenu)의 newMenu, return MenuDto(menu)의 menu가 빨간줄이 든다면, 앞에서 나온 dto에서 해당 항목이 없다는 뜻이라 생성자를 생성해야 한다.
data class MenuDto(
val id: Long?,
val name: String,
val description: String,
val price: Int
) {
companion object {
fun from(menu: Menu): MenuDto {
return MenuDto(menu.id, menu.name, menu.description, menu.price)
}
}
}
이걸
data class MenuDto(
val id: Long?,
val name: String,
val description: String,
val price: Int
) {
constructor(menu: Menu) : this(
id = menu.id,
name = menu.name,
description = menu.description,
price = menu.price
)
companion object {
fun from(menu: Menu): MenuDto {
return MenuDto(menu.id, menu.name, menu.description, menu.price)
}
}
}
그런데, return ResponseEntity.status(HttpStatus.CREATED).body(MenuDto(menu))에서 menu가 빨간줄이 나오는게 아닌가? 이 경우에는
@Operation(summary = "새 메뉴 생성", description = "새로운 메뉴를 생성합니다.")
@PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
fun createMenu(
@Parameter(description = "생성할 메뉴 정보") @RequestBody menuCreateDto: MenuCreateDto
): ResponseEntity<out Any> {
val menu = menuService.createMenu(menuCreateDto)
return ResponseEntity.status(HttpStatus.CREATED).body(MenuDto(menu))
}
이걸
@Operation(summary = "새 메뉴 생성", description = "새로운 메뉴를 생성합니다.")
@PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
fun createMenu(
@Parameter(description = "생성할 메뉴 정보") @RequestBody menuCreateDto: MenuCreateDto
): ResponseEntity<out Any> {
val menuDto = menuService.createMenu(menuCreateDto)
return ResponseEntity.status(HttpStatus.CREATED).body(menuDto)
}
이 오류가 발생한 이유는, dto를 만들어서 생성을 거기에 맡겨놨는데 dto가 아니라 menu에서 받아오려니 충돌이 일어났던 모양이다. 그래서 앞의 menu는 dto로 만들고 뒤의 메뉴는 빼버려야 한다.
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
@Operation(summary = "모든 메뉴 조회", description = "모든 메뉴를 조회합니다.")
fun getMenus(): ResponseEntity<out Any> {
val menus = menuService.getMenus()
return if (menus.isNotEmpty()) {
ResponseEntity.ok(menus)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(mapOf("message" to "메뉴가 존재하지 않습니다."))
}
}
여기에서 getMenus가 빨간색이였는데, 그 이유는
interface MenuService {
fun createMenu(menuCreateDto: MenuCreateDto): MenuDto
fun updateMenu(id: Long, menuUpdateDto: MenuUpdateDto): MenuDto
fun getMenu(id: Long): MenuDto
fun getAllMenus(): List<MenuDto> // 모든 메뉴를 조회하여 List<MenuDto>를 반환
fun deleteMenu(id: Long)
}
여기에서 볼수 있듯이 일반 getmenu는 하나만 조회, getAllMenus가 모든 메뉴 조회인데 getallmenu 대신 getmenu를 써서 생긴 일이였다.
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-01-22T20:25:00.587+09:00 ERROR 21508 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
이오류가 떠서 붠가 했더니, 데이터베이스가 연결되지 않아서 생긴 일이였다. 이건 나중에라도 연결하면 되니까... 지금은 넘어가자!!
@RestController
@Tag(name = "Menu", description = "메뉴 API")
@RequestMapping("/menus")
class MenuController(private val menuService: MenuService) {
@Operation(summary = "메뉴 정보 업데이트", description = "주어진 메뉴 ID에 해당하는 메뉴의 정보를 업데이트합니다.")
@PutMapping("/{menuId}", produces = [MediaType.APPLICATION_JSON_VALUE])
fun updateMenu(
@Parameter(description = "메뉴 ID") @PathVariable menuId: Long,
@Parameter(description = "업데이트할 메뉴 정보") @RequestBody menuUpdateDTO: MenuUpdateDto
): ResponseEntity<out Any> {
val menu = menuService.getMenu(menuId)
return if (menu != null) {
menuService.updateMenu(menuId, menuUpdateDTO)
ResponseEntity.ok(menuUpdateDTO)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(mapOf("message" to "존재하지 않는 메뉴입니다."))
}
}
여기에서 menu != null이 노란색인게 거슬린다! 그게 노란색인 이유는 menu != null은 널인지 안닌지를 확인해 주는데, private val이 있어서 null이 올수 없는데도 있어서 그런거였다.
@RestController
@Tag(name = "Menu", description = "메뉴 API")
@RequestMapping("/menus")
class MenuController(private val menuService: MenuService) {
@Operation(summary = "메뉴 정보 업데이트", description = "주어진 메뉴 ID에 해당하는 메뉴의 정보를 업데이트합니다.")
@PutMapping("/{menuId}", produces = [MediaType.APPLICATION_JSON_VALUE])
fun updateMenu(
@Parameter(description = "메뉴 ID") @PathVariable menuId: Long,
@Parameter(description = "업데이트할 메뉴 정보") @RequestBody menuUpdateDTO: MenuUpdateDto
): ResponseEntity<out Any> {
val menu = menuService.getMenu(menuId)
return if (menu != null) {
menuService.updateMenu(menuId, menuUpdateDTO)
ResponseEntity.ok(menuUpdateDTO)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(mapOf("message" to "존재하지 않는 메뉴입니다."))
}
}
@Operation(summary = "새 메뉴 생성", description = "새로운 메뉴를 생성합니다.")
@PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
fun createMenu(
@Parameter(description = "생성할 메뉴 정보") @RequestBody menuCreateDto: MenuCreateDto
): ResponseEntity<out Any> {
val menuDto = menuService.createMenu(menuCreateDto)
return ResponseEntity.status(HttpStatus.CREATED).body(menuDto)
}
@Operation(summary = "메뉴 삭제", description = "주어진 메뉴 ID에 해당하는 메뉴를 삭제합니다.")
@DeleteMapping("/{menuId}", produces = [MediaType.TEXT_PLAIN_VALUE])
fun deleteMenu(
@Parameter(description = "메뉴 ID") @PathVariable menuId: Long
): ResponseEntity<out Any> {
val menu = menuService.getMenu(menuId)
return if (menu != null) {
menuService.deleteMenu(menuId)
ResponseEntity.ok(mapOf("message" to "메뉴를 삭제하였습니다."))
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body("존재하지 않는 메뉴입니다.")
}
}
@GetMapping("/{menuId}", produces = [MediaType.APPLICATION_JSON_VALUE])
@Operation(summary = "특정 메뉴 조회", description = "주어진 메뉴 ID에 해당하는 메뉴를 조회합니다.")
fun getMenu(
@Parameter(description = "메뉴 ID") @PathVariable menuId: Long
): ResponseEntity<out Any> {
val menu = menuService.getMenu(menuId)
return if (menu != null) {
ResponseEntity.ok(menu)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(mapOf("message" to "존재하지 않는 메뉴입니다."))
}
}
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
@Operation(summary = "모든 메뉴 조회", description = "모든 메뉴를 조회합니다.")
fun getMenus(): ResponseEntity<out Any> {
val menus = menuService.getAllMenus()
return if (menus.isNotEmpty()) {
ResponseEntity.ok(menus)
} else {
ResponseEntity.status(HttpStatus.NOT_FOUND).body(mapOf("message" to "메뉴가 존재하지 않습니다."))
}
}
}
이제 private만 남기고 null은 사라졌다.