20240213 (화) 개인 주특기 플러스 9일차

2024. 2. 13. 20:58TIL

오늘은   JpaAuditing을 이용한 생성과 수정시간 자동기록, SignUp 단계에서 UserRole을 Enum으로 받는 방법 등 여러가지를 추가해봤다.

 

1. JpaAuditing을 이용한 생성과 수정시간 자동기록

 

우선 어플리케이션에 어노테이션으로 JpaAuditing을 쓸것이라고 선언해준다.

 

package lsw.practice

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.jpa.repository.config.EnableJpaAuditing

@SpringBootApplication
@EnableJpaAuditing //추가
class PracticeApplication

fun main(args: Array<String>) {
    runApplication<PracticeApplication>(*args)
}

 

그다음 상속시켜줄 BaseTime 클래스를 만들건데, 위치를 어디로 잡을지 고민하다가 결국은 유저가 남기는 시간을 기준으로 찍히는거니까 User 패키지의 User엔티티가 있는 Model 쪽에 넣어주기로했다.

 

package lsw.practice.domain.user.model

import jakarta.persistence.Column
import jakarta.persistence.EntityListeners
import jakarta.persistence.MappedSuperclass
import org.hibernate.annotations.CreationTimestamp
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.LocalDateTime

@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class BaseTime {
    @CreationTimestamp
    @Column(nullable = false, updatable = false)
    val createdAt: LocalDateTime? = null

    @CreationTimestamp
    @Column(nullable = false)
    val updatedAt: LocalDateTime? = null
}

여기서 createdAt은 처음에 작성된 이후로 수정되면 안되기에 updatable을 false로 해줬다.

 

이후엔 BaseTime 클래스를 상속받아서 기록 자동화를 할 Entity에 상속시키기만 하면 끝!

 

package lsw.practice.domain.post.model

import jakarta.persistence.*
import lsw.practice.domain.comment.model.Comment
import lsw.practice.domain.user.model.BaseTime
import lsw.practice.domain.user.model.User
import org.hibernate.annotations.OnDelete
import org.hibernate.annotations.OnDeleteAction
import org.hibernate.annotations.SQLDelete
import org.hibernate.annotations.Where
import java.time.LocalDateTime

@Entity
@SQLDelete(sql = "UPDATE post SET is_deleted = true WHERE id = ?") // DELETE 쿼리 날아올 시 대신 실행
@Where(clause = "is_deleted = false")
@OnDelete(action = OnDeleteAction.CASCADE)
@Table(name = "post")
class Post(

    @Column(name = "title", nullable = false)
    var title: String,

    @Column(name = "content", nullable = false)
    var content: String,

//    @Column(name = "created_at", nullable = false)
//    var createdAt: LocalDateTime = LocalDateTime.now(),

    @Column(name = "is_deleted", nullable = false)
    var isDeleted : Boolean = false,

    @ManyToOne(
        fetch = FetchType.LAZY,
        cascade = [CascadeType.ALL]
    )
    @JoinColumn(name = "user_id", nullable = false)
    var user: User,

    @Column(name = "name", nullable = false)
    var name: String,

    @OneToMany(
        mappedBy = "post",
        cascade = [CascadeType.ALL],
        orphanRemoval = true,
        fetch = FetchType.LAZY
    )
    var comments: MutableList<Comment> = mutableListOf(),
): BaseTime() {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null

    fun addComment(comment: Comment) {
        comments.add(comment)
    }

    fun removeComment(comment: Comment) {
        comments.remove(comment)
    }
}

 

기존에 있던 createdAt은 주석처리를 해놓았다.

 

이렇게하면 자동으로 기록해준다.

 

2. SignUp 단계에서 UserRole을 Enum으로 받기

 

나는 기존에 Role을 스트링으로 SignUp시에 RequestBody에서 받아오고 ServiceImpl에서 스트링을 Enum으로 바꾸는 코드를 하나 더 썼다.

 

하지만 이번엔 RequestParam으로 Enum클래스를 바로 받아서 둘중에 하나만 고를수 있도록 해주고 거기서 고른 Role을 회원가입시에 추가해주는 형식으로 바꿔봤다.

@PostMapping("/signup")
fun signUp(
    @RequestParam userRole: UserRole,
    @Valid @RequestBody signUpRequest: SignUpRequest): ResponseEntity<UserResponse> {
    return ResponseEntity
        .status(HttpStatus.CREATED)
        .body(userService.signUp(userRole, signUpRequest))
}

 

Swagger에서 드롭다운 형태로 바뀐 상태

 

위에는 실제코드, 아래는 코드가 적용된 Swagger

 

이렇게 하니까 우선 내가 설정해놓은 USER, ADMIN 이외에 역할이 들어갈 일은 사라진게 가장 좋은점 같다.

그리고 코드면에서도 기존 String을 Enum으로 바꾸는 코드를 쓸필요없이 Param값을 그대로 적용하면 돼서 간결해졌다.

 

3. Validation 적용해보기

 

이전에 Validation을 적용했는데 제대로 작동이 안됐다.

이유를 보니 단순하게 gradle 을 추가해주지 않아서였다. (Valid가 특이한건지 gradle 적용 전에 어노테이션을 써도 Import가 잘 됐다.)

 

아래는  gradle에 추가한 Validation

implementation("org.springframework.boot:spring-boot-starter-validation")//벨리데이션

 


오늘은 제출일이기도 해서 진행할 시간도 많지 않았다.

따라서 강의보단 실전작업 위주로 진행했다.

내일부터는 프로젝트가 시작되는데 살짝 걱정도 된다.