본문 바로가기

카테고리 없음

24.01.22 백오피스 1

 

커밋을 할때 인텔리제이의 터미널만이 아니라  왼쪽에서 창을 띄우고 거기에 메시지를 입력한뒤 커빗 버튼을 눌러도 된다는걸 처음 알았다.

 

그리고 여럿이서 협력할때는 깃허브를 생성하고서 이슈를 눌러서 거기에 각자 생성할것에 대한 체크리스트를 작성하고

 

 

@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은 사라졌다.