์๋
ํ์ธ์.
์ฝํ๋ฆฐ๊ณผ ์คํ๋ง์ ์ฆ๊ฒ๊ฒ ๊ณต๋ถํ๊ณ ์๋ ๊ฐ๋ฐ์์
๋๋ค.
ํ์ฌ 10๋
์ฐจ ๊ฐ๋ฐ์๋ก ํํ
ํฌ ์คํํธ์
์ ์์ต๋๋ค.
๊ฐ์๋ฅผ ์ ์ํ๋ฉด์ ์ ์ค์ค๋ก๋ ๋ ๊ณต๋ถ๋ฅผ ํ๊ณ ์ ๊ฐ ๊ณต๋ถํ ์ง์๋ค์ ๊ณต์ ํ๊ณ ์ถ์ด์ ์ด๋ ๊ฒ ๊ฐ์๋ฅผ ๋ง๋ค๊ฒ ๋์์ต๋๋ค.
Courses
Reviews
- [Beginner] Let's Eat! Create Membership with Kotlin and Spring Security + JWT
- [Beginner] Let's try it! Calling API with Kotlin and Spring
- [Beginner] Let's tear it apart! Everything about Kotlin
- [Beginner] Let's try it! Calling API with Kotlin and Spring
- [Beginner] Let's Eat! Create Membership with Kotlin and Spring Security + JWT
Posts
Q&A
DTO ์์ฑ ๊ณผ์ ์์ ๊ถ๊ธํ ์ ์ด ์์ด์!!
์ด์ ์ ์ด์ ๊ด๋ จ๋ ์ง๋ฌธ์ ๋จ๊ฒจ์ฃผ์ ๋ถ์ด ๊ณ์ ์ ํด๋น ๊ธ ์ฝ์ด๋ณด์๋ฉด ๋์๋์ค ๊ฒ ๊ฐ์ต๋๋ค.๊ฐ์ฌํฉ๋๋ค.https://www.inflearn.com/questions/1012428/validation-%EA%B4%80%EB%A0%A8%ED%95%B4%EC%84%9C-%EC%A7%88%EB%AC%B8%EB%93%9C%EB%A6%BD%EB%8B%88%EB%8B%A4
- 0
- 3
- 479
Q&A
2.5๊ฐ์์ ํฌ์คํธ๋งจ ์ค๋ฅ์ ์ ์ ์ค์ตํ ๋ด์ฉ์ ๋ํด ์ง๋ฌธ ๋๋ฆฝ๋๋ค
์๋ ํ์ธ์ ์ฌ์ฑ๋. ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ ๊ฐ ์ง์ ์ฌ์ฑ๋์ ์์ค๋ฅผ ๋ณด์ง๋ฅผ ๋ชปํด์ ์ ํํ ์์ธ ํ์ ์ ์ด๋ ค์ฐ๋์์ฑํ์ ๋ด์ฉ ๊ธฐ์ค์ผ๋ก ๋ณด๋ฉด ์๋ง๋ ๋ ๊ฐ์๋ฅผ ํ๋์ ํ๋ก์ ํธ์์ ์์ฑํ์ ์ @RestControllerAdvice์์ ์๋ ExceptionHandler๊ฐ ์ค๋ณต์ด ๋์ ๋ฌธ์ ๊ฐ ์ผ์ด๋ ๊ฒ์ผ๋ก ์ถ์ธก๋ฉ๋๋ค. ๋ ๊ฐ์๊ฐ ๋ฐ๋ก ์์ฑ๋ ๊ฒ์ด์ฌ์ ๋ณ๋์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด์ ์งํํ์๊ธฐ๋ฅผ ๊ถ์ฅ ๋๋ฆฝ๋๋ค.๊ทธ๋ฆฌ๊ณ ํ์ฌ ํ๋์ ํ๋ก์ ํธ์์ ์ฌ์ฉํ์๋ ค๋ฉด ์ค๋ณต๋๋ ExceptionHandler๋ฅผ ์ ๊ฑฐํด์ Exception์ด ๋ฐ์ํ์๋ ํ๊ณณ์์๋ง ๋ฐ์ ์ฒ๋ฆฌํ๋ฉด ํด๊ฒฐ๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
- 0
- 2
- 500
Q&A
DTO ์์ฑ ๊ณผ์ ์์ ๊ถ๊ธํ ์ ์ด ์์ด์!!
์๋ ํ์ธ์ ํ์์ฃผ๋์ด๋.์ง๋ฌธ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.DTO ์์ฑํ ๋ ์ข ๋ ๊ฐํธํ๊ณ ์ฝ๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ง๋ฌธ ์ฃผ์ จ๋๋ฐ data class ๋์ ์ class๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. data class LoginDto( @field:NotBlank @JsonProperty("loginId") private val _loginId: String?, @field:NotBlank @JsonProperty("password") private val _password: String?, ) { val loginId: String get() = _loginId!! val password: String get() = _password!! } class LoginDto( loginId: String?, password: String?, ) { @field:NotBlank val loginId: String = loginId ?: "" @field:NotBlank val password: String = password ?: "" }class๋ฅผ ์ฌ์ฉํด์ null ํ์ฉ ํ์ ์ผ๋ก ์ผ๋จ DTO์ ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์ค๊ดํธ ์์ ํ๋กํผํฐ๋ฅผ ๋๊ณ validation ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ ์ฒดํฌ๋ฅผ ํ๋ฉด์ null ๋ถ๊ฐ ํ์ ์ DTO๋ฅผ ์ฌ์ฉ์ null ๊ณ ๋ ค์์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
- 0
- 3
- 479
Q&A
1 : N ํ๋ `memberRole` ์ @OneToMany ์ต์ cascade ๋ฏธ์ฌ์ฉ, ์ปฌ๋์ null ์ด๊ธฐํ ์ ๋ํ ์ง๋ฌธ์ ๋๋ค.
์๋ ํ์ธ์. Truestar๋ ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.๋๊ฐ์ง ์ง๋ฌธ์ ๋ต๋ณ์ ๊ฐ์ด ๋จ๊ธฐ์๋ฉด ํด๋น ๊ฐ์๊ฐ ์ด๋ณด์๋ฅผ ๋์์ผ๋ก Spring Security์ JWT๋ฅผ ํ๋ฒ ์ฌ์ฉํด๋ณด๋ ๊ฐ์์ฌ์ ์์ ๊ฐ ๊ทธ๋ ๊ฒ ๋์์ต๋๋ค.Q1. cascade ๋ฏธ์ฌ์ฉ=> cascade ๋ฅผ ์ฌ์ฉํ๋ฉด์ ์ค๋ช ์ ํ๋ ค๋ฉด ์์์ฑ ์ปจํ ์คํธ๋ฅผ ๊ฐ์ด ์ค๋ช ์ ํด์ผํด์ ํด๋น ๋ถ๋ถ์ ์ ์ธํ๊ณ ์๋น์ค์์ ๋ฐ๋ก ๋ฃ์ด์ฃผ๋ ์ฝ๋๋ฅผ ์์ฑํ์์ต๋๋ค. ๋ค๋ฅธ ์ด์ ๋ ์๊ณ ์ด๋ ๊ฒ ํ๋๊ฒ ์ด๋ณด์๋ถ๋ค์ด ์ดํดํ์๋๋ฐ ์ฌ์ธ ๊ฒ์ผ๋ก ํ๋จํ์ต๋๋ค. Q2. ์ปฌ๋ ์ null ์ด๊ธฐํ=> ์ด๊ฒ๋ ๋ด์ฉ์ ๋์ผํฉ๋๋ค.@OneToMany(fetch = FetchType.LAZY, mappedBy = "member") val memberRole: List? = nullํด๋น ์์ ์์ memberRole์ ๊ถํ ํ์ธ์ ์กฐํ์ฉ์ผ๋ก๋ง ์ฐ๋ ค๊ณ ํ์ต๋๋ค.ํ์๊ฐ์ ์ DB์ ๋ฐ๋ก ์ ์ฅ๋ง ํ๊ณ ๋๋๊ธฐ์ memberRoleRepository๋ฅผ ์ฌ์ฉํด์ memberRole์ ์ ์ฅํ๋ฉด์ member ์ํฐํฐ์ ์ฐ๊ฒฐํด์ฃผ์ง ์์์ต๋๋ค.๊ทธ๋์ ๋น ๋ฆฌ์คํธ๋ก ๋ฏธ๋ฆฌ ์ด๊ธฐํํ ํ์๊ฐ ์์ด์ null๋ก ๋ฃ์์ต๋๋ค. ์ค์ ๊ฐ๋ฐ์ ํ ๋๋ ์ฌ๋ฌ๊ฐ์ง๋ฅผ ๊ณ ๋ คํด์ ๊ฐ๋ฐ์ ์งํํ์ง๋ง ํด๋น ๊ฐ์๋ ์ด๋ณด์๊ฐ ์ฝ๊ฒ ๋ฐ๋ผํ ์ ์๋ ๊ฐ์๋ฅผ ๋ง๋๋๋ฐ ํฌ์ปค์ฑ์ ๋๊ณ ์์ด์ ๋ณด์ค๋ ์ด์ํ ์์ ๊ฐ ์์ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ค์๋ฒ์๋ ์ข ๋ ํ์คํ๊ณ ์ฌ์ด ์์ ๋ก ์ฐพ์๋ต๋๋ก ํ๊ฒ ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค :)
- 0
- 2
- 355
Q&A
build.gradle.kts ์ค๋ฅ๊ฐ ๋ฐ์ํด์
์๋ ํ์ธ์ ์ฌ์ฑ๋ ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๋ค์ ๋น๋ํด์ ํด๊ฒฐ๋์ง ์์๋ค๋ฉด ์บ์ ๋ฌธ์ ๊ฐ ์๋๊น ์๊ฐ๋ฉ๋๋ค.File -> Invalidate Caches... -> Invalidate and Restart ๋๋ฌ์ IntelliJ ๋ค์ ์์ํด๋ณด์๋ฉด ํด๊ฒฐ ๋ ์๋ ์์ต๋๋ค. (์ฌ์ง)(์ฌ์ง)ํ๋ฒ ํด๋ณด์๊ณ ์๋์๋ฉด ๋ค์ ์ง๋ฌธ ๋ถํ๋๋ฆฝ๋๋ค. ๊ฐ์ฌํฉ๋๋ค :)
- 0
- 2
- 2.3K
Q&A
loginId๋ ์ ๋ณ๊ฒฝ์ด ์๋ ๊น์?
์๋ ํ์ธ์ jjang9๋ ์ง๋ฌธ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ํ์์ ๋ณด ์์ ํ๋ ๋ถ๋ถ ์ง๋ฌธ ์ฃผ์ จ๋๋ฐ์.์ด๊ฑฐ๋ JPA ์ค์ ์ค์ update์์๋ loginId๋ ์์ ์ด ๋์ง ์๊ฒ ํด๋์๊ธฐ ๋๋ฌธ์ ๋๋ค.class Member( @Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Long? = null, @Column(nullable = false, length = 30, updatable = false) val loginId: String, @Column(nullable = false, length = 100) val password: String, @Column(nullable = false, length = 10) val name: String, @Column(nullable = false) @Temporal(TemporalType.DATE) val birthDate: LocalDate, @Column(nullable = false, length = 5) @Enumerated(EnumType.STRING) val gender: Gender, @Column(nullable = false, length = 30) val email: String, )Member entity๋ณด์๋ฉด loginId ์์ ์ค์ ์ ๋จน์ฌ๋๋๋ฐ updatable = false ๋ผ๊ณ ํด๋๋ฉด ํด๋น ์ปฌ๋ผ์ insert๋๋ง ๋ฃ๊ณ update ํ ๋๋ ์ ์ธํ๊ฒ ๋ฉ๋๋ค.@Column(nullable = false, length = 30, updatable = false)๊ทธ๋์ ํ์์ ๋ณด ์์ ์ ํ ๋ loginId๊ฐ ๋ณํ์ง ์๊ฒ ๋ฉ๋๋ค.ํด๋น ์ค์ ํ์ด๋ณด์๊ณ ํ์์ ๋ณด ์์ ํด๋ณด์๋ฉด loginId๊ฐ ๋ณ๊ฒฝ ๋ ๊ฒ๋๋ค. ๋ ๊ถ๊ธํ์ ์ ์์ผ์๋ฉด ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ธ์~๊ฐ์ฌํฉ๋๋ค :)
- 0
- 1
- 334
Q&A
Validation ๊ด๋ จํด์ ์ง๋ฌธ๋๋ฆฝ๋๋ค.
JUNN๋ ์ถ๊ฐ๋ก ์ง๋ฌธ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.JUNN๋ ์ง๋ฌธ์ ์ฝ๊ณ ๋ค์ ํ๋ฒ DTO๋ฅผ ์ด๋ค์์ผ๋ก ํ์ฉํ๋๊ฒ ์ข์์ง ์๊ฐํด๋ดค์ต๋๋ค.RequestDto์ ๊ฒฝ์ฐ ๋ชจ๋ ๊ฐ์ด ๋ค ๋ด๊ฒจ์ ธ ์์ด์ผ ํ๋ค๋ฉด ์ ๊ผญ null ๋๋ "" ์ ํ์ฉํด์ค์ผ ํ๋๊ฐ? ์ด๊ฑธ ํ์ฉ ์ ํด์ค๋ค๋ฉด String? ์ด ์๋ String์ ์ฌ์ฉํ๋ฉด ์ ๋๋ ๊ฒ์ผ๊น?=> ์ด ๋ถ๋ถ์ ํ๋ก ํธ์ชฝ๊ณผ ๊ฐ์ ์ฃผ๊ณ ๋ฐ๋ ๋ถ๋ถ์ด ๋ง์๋จ์ด์ง๋ค๋ฉด String์ผ๋ก ์ ์ธํ์ ๋ ๋ฉ๋๋ค. ์ ์ด์ ํ๋ก ํธ์์ null์ด๋ ""๋ฅผ ๋๊ธฐ์ง ์์ํ ๋๊น์. ๊ทธ๋ฐ๋ฐ String?์ผ๋ก ํ๋ ์ด์ ๋ฅผ ์กฐ๊ธ ๋ง์๋๋ฆฌ์๋ฉด ์ ๋ ํด๋ผ์ด์ธํธ(ํ๋ก ํธํ๋ฉด์ผ ์๋ ์๊ณ postman์ผ์๋ ์๋)์์ ์ค๋ Request๋ ์ธ์ ๋ ์ง ํ๋ฆด ์ ์๋ค๋ ์ ์ ๊ฐ ์์ต๋๋ค. ๊ทธ๋์ ๊ทธ๊ฒ์ ๊ฒ์ฆํ๋ ์ผํ์ผ๋ก Validation์ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค. Request body์ ์๋์ ๊ฐ์ ์ ๋ฌํ๋ค๊ณ ๊ฐ์ ํด๋ณด๊ฒ ์ต๋๋ค.(loginId, password ํ์๊ฐ){ "loginId":null, "password":null } String ์ผ๋ก ์ ์ธclass LoginDto( @field:NotBlank val loginId: String, @field:NotBlank val password: String, )String์ผ๋ก ์ ์ธํ๊ณ ๊ฐ์ ์ ๋ฌํ๋ฉด request์ ์๋์ ๊ฐ์ด ๋์ค๊ฒ ๋ฉ๋๋ค.{ "resultCode": "ERROR", "data": { "๋ฏธ์ฒ๋ฆฌ ์๋ฌ": "JSON parse error: Instantiation of [simple type, class com.example.auth.member.dto.LoginDto] value failed for JSON property loginId due to missing (therefore NULL) value for creator parameter loginId which is a non-nullable type" }, "message": "์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }๊ทธ๋ฌ๋ฉด loginId์ null์ ๋ฃ์ ์ ์๋ค๊ณ error๋ฉ์ธ์ง๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ฉ๋๋ค. String? ์ผ๋ก ์ ์ธclass LoginDto( @field:NotBlank val loginId: String?, @field:NotBlank val password: String?, )String?์ผ๋ก ์ ์ธํ๊ณ ๊ฐ์ ์ ๋ฌํ๋ฉด request์ ์๋์ ๊ฐ์ด ๋์ค๊ฒ ๋ฉ๋๋ค.{ "resultCode": "ERROR", "data": { "loginId": "๊ณต๋ฐฑ์ผ ์ ์์ต๋๋ค", "password": "๊ณต๋ฐฑ์ผ ์ ์์ต๋๋ค" }, "message": "์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }๊ทธ๋ฌ๋ฉด loginId, password ๋ ๋ค ์๋๋ ์ด์ ๋ฅผ Response์ ๋ด์์ ๋ณด๋ด์ค ์ ์์ต๋๋ค. ์ด๊ฒ์ผ๋ก ๋ณด๋ฉด String์ผ๋ก ์ ์ธํ๋ฉด Validation ์ฒดํฌ๋ฅผ ํ๊ธฐ ์ ์ DTO์ ๋ด๋ ๊ณผ์ ์์ error๋ฅผ ๋ฐ์์ํค๋ ๊ฒ์ ์ ์ ์๋๋ฐ์. ์๋ฅผ ๋ค์ด ํญ๋ชฉ์ด 10๊ฐ์ธ๋ฐ ๊ทธ ํญ๋ชฉ๋ค ๋ชจ๋ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ์ํฉ์ ๋ฐ๋ผ ๋ฌธ์ ๊ฐ ์๋ 1๊ฐ์ ํญ๋ชฉ๋ง Request ๋ณด๋ธ ์ชฝ์์ ์ ์ ์์ต๋๋ค. String?๋ก ์ ์ธํด์ DTO์ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ๊ณผ์ ์์ ๋ฌธ์ ๋ฅผ ๋ฐ์์ํค์ง ์๋๋ค๋ฉด Validation์ผ๋ก ๋ชจ๋ ํญ๋ชฉ์ ๊ฒ์ฌํ๊ณ ๋ชจ๋ ๋ฌธ์ ๋ฅผ Request ๋ณด๋ธ ์ชฝ์ ์๋ ค ์ค ์ ์์ต๋๋ค.{ "resultCode": "ERROR", "data": { "loginId": "๊ณต๋ฐฑ์ผ ์ ์์ต๋๋ค", "name": "๊ณต๋ฐฑ์ผ ์ ์์ต๋๋ค", "birthDate": "๋ ์งํ์(YYYY-MM-DD)์ ํ์ธํด์ฃผ์ธ์", "password": "์๋ฌธ, ์ซ์, ํน์๋ฌธ์๋ฅผ ํฌํจํ 8~20์๋ฆฌ๋ก ์ ๋ ฅํด์ฃผ์ธ์", "gender": "MAN ์ด๋ WOMAN ์ค ํ๋๋ฅผ ์ ํํด์ฃผ์ธ์", "email": "์ฌ๋ฐ๋ฅธ ํ์์ ์ด๋ฉ์ผ ์ฃผ์์ฌ์ผ ํฉ๋๋ค" }, "message": "์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค." }๊ทธ๋์ ํ์๊ฐ์ ์ชฝ์ ๋ณด์๋ฉด Validation์ผ๋ก ์ฒ๋ฆฌํ์๋์ ์ฅ์ ์ ๋ณด์ค ์ ์์ต๋๋ค. 1๋ฒ๊ณผ ๊ฐ์ ์ ๊ทผ์ด๋ผ๋ฉด UpdateDto์ ๊ฒฝ์ฐ์ ๋ง์ฝ ๋ชจ๋ ๊ฐ์ ์์ ํ๋ ๊ฒ์ด ์๋๋ผ ์ผ๋ถ ํ๋กํผํฐ์๋ง ๊ฐ์ด ๋ด๊ฒจ์ ธ์ ์ค๋ฉด ์ด๋ด ๋๋ String? ํ์ ์ ์ฌ์ฉํด์ผ ๋๋ ๊ฒ์ผ๊น?=> ์ ์ ์๋น์ค ์ด์ ๊ด์ ์์ ๋ณธ๋ค๋ฉด update๋ฅผ ํด์ผํ๋ ๊ฒฝ์ฐ ์ผ๋ถ ๊ฐ์ด ๋ณ๊ฒฝ์ด ๋์ด๋ ํญ๋ชฉ๋ค ์ ์ฒด๋ฅผ ๋ฐ์์ ์ ์ฒด๋ฅผ update์น๋๊ฒ ์ข๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ผ๋ถ๋ฅผ updateํ๊ฒ ๋๋ฉด ๋ ํจ์จ์ ์ผ๋ก ๋ณด์ผ ์ ์๊ฒ ์ผ๋ ๊ฐ ํญ๋ชฉ์ ๋ณ๊ฒฝ์์ ๊ณผ ๋ณ๊ฒฝ์๊ฐ ๋ฌ๋ผ์ ธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋ ์์ธ์ ์ฐพ์๊ฐ๋ ๊ฒ์ ์ถ๊ฐ์ ์ธ ๋ฆฌ์์ค๊ฐ ๋ฐ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.์ผ๋ถ ํ๋กํผํฐ๋ง ๊ฐ์ ์ ๋ฐ์ดํธ ์น๋ ๊ฒ์ผ๋ก ์๋ฅผ ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.name : "ํ๊ธธ๋", age : 30 ๋ผ๋ ์ ๋ณด๋ฅผ A์ ์ ๋ name = "์๊บฝ์ "B์ ์ ๋ age = 40์ผ๋ก ์ ๋ฐ์ดํธ์น๋ Request๋ฅผ ๊ฐ์ ์์ ์ ๋ณด๋๋ค๊ณ ํ๋ฉด A์ ์ ์ฅ์์๋ name๋ง ๋ณ๊ฒฝํ๋๋ฐ age๊น์ง ๋ณ๊ฒฝ์ด ๋ ๊ฒ์ผ๋ก ๋ณด์ผ๊ฒ๋๋ค. B๋ ๋ง์ฐฌ๊ฐ์ง ์ ์ฅ์ด๊ฒ ์ฃ . ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅด์ง๋ง 2๊ฐ์ง update ๊ฐ ๋์ด์ฌ๋ ์ต์ข ๋ณ๊ฒฝ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋๋ก ๋ง๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.๊ทธ๋์ ์ ์ฒด ํญ๋ชฉ์ ๋ฐ์์ ํ์ฌ ๋ฐ์ดํฐ์ ์ ๋ฐ์ดํธ๋ฅผ ์น๋ ๊ฒ์ด์ฃ A์ ์ ์ ์ ๋ฐ์ดํธ๊ฐ ๋จผ์ ์คํ๋๋ค๋ฉด B์ ์ ์ name = "ํ๊ธธ๋", age = 40์ผ๋ก ๋ฎ์ด์์ ์ต์ข ์ ์ผ๋ก B์ ์ ์ ์ ๋ณด๋ง ๋จ๊ฒ ๋ฉ๋๋ค.์์๊ฐ ์ ์ ํ์ง ์์์ ์ ์์ผ๋ ์ด๋ฐ ๊ด์ ์์ ๋ณธ๋ค๋ฉด ์ ์ฒด ํ๋กํผํฐ๋ฅผ ๋ฐ๊ฒ ๋๋ ๊ฒ์ด๊ณ ๊ฐ ํ๋กํผํฐ์ ์ฑ๊ฒฉ์ ๋ฐ๋ผ์ ํ์ ๊ณผ Validation์ ์ง์ ํ๋ ๊ฒ์ด ์ข์ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐ๋ฉ๋๋ค. ์ง๋ฌธ์ ๋ํ ์ ์ ํ ๋ต์ด ๋์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ์ ๋ JUNN๋ ๋๋ถ์ ํด์๋๋๋ก ๊ทธ๋ฅ ๊ฐ๋ฐ์ ํ์ง ์์๋์ง ์ด ๋ถ๋ถ์ ์ ์ด๋ ๊ฒ ์ฌ์ฉํ์๋์ง ๋ค์ ํ๋ฒ ์๊ฐํ๊ฒ ๋์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค. ์์ผ๋ก ๋ ๊ถ๊ธํ์ ์ ์๊ธฐ์๋ฉด ์ธ์ ๋ ์ง ์ง๋ฌธ ๋ถํ๋๋ฆฝ๋๋ค.๊ฐ์ฌํฉ๋๋ค :)
- 1
- 2
- 674
Q&A
memberRoleํ๋ ์ง๋ฌธ์ด์~
์๋ ํ์ธ์. juuu o๋ ์ง๋ฌธ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.@Entity @Table( uniqueConstraints = [UniqueConstraint(name = "uk_member_login_id", columnNames = ["loginId"])] ) class Member( @Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Long? = null, @Column(nullable = false, length = 30, updatable = false) val loginId: String, @Column(nullable = false, length = 100) val password: String, @Column(nullable = false, length = 10) val name: String, @Column(nullable = false) @Temporal(TemporalType.DATE) val birthDate: LocalDate, @Column(nullable = false, length = 5) @Enumerated(EnumType.STRING) val gender: Gender, @Column(nullable = false, length = 30) val email: String, ) { @OneToMany(fetch = FetchType.LAZY, mappedBy = "member") val memberRole: List? = null private fun LocalDate.formatDate(): String = this.format(DateTimeFormatter.ofPattern("yyyyMMdd")) fun toDto(): MemberDtoResponse = MemberDtoResponse(id!!, loginId, name, birthDate.formatDate(), gender.desc, email) }์ด ์ํฐํฐ์์ ์ง๋ฌธ์ฃผ์ ๋ถ๋ถ์ MemberRole๊ณผ ์กฐ์ธ์ ์ํ ํ๋กํผํฐ์ธ๋ฐ์.@OneToMany(fetch = FetchType.LAZY, mappedBy = "member") val memberRole: List? = null์๋์ ํด๋์ค๋ฅผ ํ์ด์ ์ ์ด๋ณด๋ฉด constructor๊ฐ ์๋ต์ด ๋์ด์๋ ํํ์ ๋๋ค.class Member( ... ) -> class Member constructor( ... )๊ทธ๋์ ์ค๊ดํธ( ... ) ์์๋ ์์ฑ์์ ์ฌ์ฉ๋ ํ๋กํผํฐ๋ง ๋ฃ์ด์ฃผ๋ฉด ๋๊ธฐ์ memberRole์ ๊ฑฐ๊ธฐ์ ์์ ํ์๊ฐ ์์ด์ ๋ณธ๋ฌธ์ ์ ์ธ ํ์ต๋๋ค. ๋ค๋ฅธ ์์๋ฅผ ๋ค์ด๋ณด์๋ฉดclass Person constructor( name: String, age: Int, ) { val name: String = name val age: Int = age val gender: String? = null }์ ์์ค๋ ์์ฑ์๋ก name๊ณผ age๋ผ๋ ๋ณ์๋ฅผ ๋ฐ์์ ๋ณธ๋ฌธ์ ์๋ name ํ๋กํผํฐ์ age ํ๋กํผํฐ์ ๋ฃ์ด์ฃผ๋ ์์ค์ธ๋ฐ์.์ด ์์ค๋ฅผ ํ๋กํผํฐ์ ์์ฑ์๋ฅผ ๋์์ ์ฌ์ฉํ๋๊ฑธ๋ก ์์ฑํ๋ฉด ์๋์ ์ฝ๋๊ฐ ๋ฉ๋๋ค.class Person( val name: String, val age: Int, ) { val gender: String? = null }๊ทธ๋์ ์ญ์ ์ค๊ดํธ( ... ) ์์๋ ์์ฑ์์ ํ์ํ ํ๋กํผํฐ๋ง ๋ค์ด๊ฐ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค. ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ด ๋์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ์ ๊ฐ ์ง๋ฌธ์ ์๋๋ฅผ ์๋ชป ์ดํดํ์ ์ ์์ผ๋ ๋ณด์๊ณ ๊ถ๊ธํ์ ์ ์์ผ์๋ฉด ์ถ๊ฐ ์ง๋ฌธ ๋ถํ๋๋ฆฝ๋๋ค. ๊ฐ์ ๋ด์ฃผ์๊ณ ์ง๋ฌธ๊น์ง ๋จ๊ฒจ์ฃผ์ ์ ๋ค์ ํ๋ฒ ๊ฐ์ฌํฉ๋๋ค :)
- 0
- 1
- 438
Q&A
Validation ๊ด๋ จํด์ ์ง๋ฌธ๋๋ฆฝ๋๋ค.
์๋ ํ์ธ์ JUNN๋ ์นญ์ฐฌ๊ณผ ํจ๊ป ์ง๋ฌธ๊น์ง ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.์ ๋ ๊ฐ์ ์๋ฃ ๋ง๋ค๋ฉด์ DTO์์ Validation ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ผ์ง ๊ณ ๋ฏผ์ ํ๋๋ฐ์. ๊ทธ๋์ ๊ทธ๋ฐ์ง ์ง๋ฌธ์ด ๋์ฑ ์๋ฟ์์ต๋๋ค. ๊ฐ์์ ๋ง๋ค์๋ LoginDto ๊ธฐ์ค์ผ๋ก ๋ค๋ฅธ ๋ฐฉ์์ ๋ง์ ๋๋ ค๋ณด๊ฒ ์ต๋๋ค.data class LoginDto( @field:NotBlank @JsonProperty("loginId") private val _loginId: String?, @field:NotBlank @JsonProperty("password") private val _password: String?, ) { val loginId: String get() = _loginId!! val password: String get() = _password!! }์ ๊ฐ DTO์ ์ด๋ฐ์์ผ๋ก ๋ง๋ค์๋ ๋ช๊ฐ์ง ์ด์ ๊ฐ ์์์ต๋๋ค.DTO์์ Validation์ฒ๋ฆฌ๋ฅผ ํ๋ค.Validation ์ฒดํฌ์ ๋น๊ฐ์ด ์๋๊ฒ ํ์ธ๋๋ฉด Service์์ ํด๋น DTO๋ฅผ ์ธ๋ null์ด ์๋์ ๋ณด์ฅํ๋ค.Request์ body์ ์๋์ ๊ฐ์ด ๋์ด์ค๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ ๋น๊ฐ์ผ๋ก ์ฌ๊ธด๋ค.ํด๋น key์ ๊ฐ์ด null๋ก ๋์ด์ค๋ ๊ฒฝ์ฐ{ "loginId":null, "password":null }ํด๋น key์ ๊ฐ์ด ""๋ก ๋์ด์ค๋ ๊ฒฝ์ฐ{ "loginId":"", "password":" " }ํด๋น key๊ฐ ์๋์ด์ค๋ ๊ฒฝ์ฐ{} ๊ทธ๋์ ์ฒ๋ฆฌ ์์๋ฅผ ์๋์ ๊ฐ์ด ์ก์์ต๋๋ค.DTO์ ๋ฐ์ดํฐ ๋ด๊ธฐ(๊ฐ์ด ์ด๋ป๊ฒ ๋์ด์ฌ์ง ๋ชจ๋ฅด๋ null์ ํ์ฉ)Validation ์ฒดํฌ๋ฝ์์ธ๋ null ๋ถ๊ฐ custom getter ๊ทธ๋์ ์ด๋ฒ์ data class๊ฐ ์๋ class๋ฅผ ์ฌ์ฉํด์ DTO๋ฅผ ๋ง๋ค์์ต๋๋ค.๋ณ๊ฒฝํ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.class LoginDto( loginId: String?, // 1 password: String?, ) { @field:NotBlank // 3 val loginId: String = loginId ?: "" // 2 @field:NotBlank val password: String = password ?: "" }์์ฑ์์์ null ํ์ฉํ์ ์ผ๋ก ๊ฐ์ ๋ฐ์์ค๊ธฐ๊ทธ๊ฒ์ ํ๋กํผํฐ์ ๋ฃ์ด์ค๋ elvis operator( ?: ) ์ฌ์ฉํด์ default ๊ฐ์ ""์ผ๋ก ๋ฃ์ด์ฃผ๊ธฐValidation ์ฒดํฌ ์ด๋ ๊ฒ ํ๋ฉด ํด๋น DTO์ ๊ฐ์ ๋ฝ์์ธ๋ null ๋ถ๊ฐ ํ์ ์ด์ฌ์ null์ด ์๋์ ๋ณด์ฅํ๊ฒ ๋ฉ๋๋ค.์ด ๋ฐฉ๋ฒ์ data class๋ฅผ ์ฌ์ฉํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค. data class๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ์์ ์ ์ธ๋ ํ๋กํผํฐ ๊ธฐ์ค์ผ๋ก equals, hashCode, toString ๋ฑ์ ํจ์๋ฅผ ์์ฑํ๋๋ฐ์. ์ง๊ธ ์ ์ํ ๋ฐฉ๋ฒ์ ๋ณธ๋ฌธ์ ํ๋กํผํฐ๋ฅผ ์ ์ธํ๋ฉด์ ์ฒ๋ฆฌ๋ฅผ ํ๊ฒ ํ ๊ฒ์ด์ฌ์ data class๋ฅผ ์ฌ์ฉํด์ ํ๋ ๋ฐฉ์์ผ๋ก๋ ์ด๋ ค์ธ๋ฏ ํฉ๋๋ค. ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋๊ณ ์ด๊ฒ์ ๊ฒ ํด๋ณด๋ฉด์ ๋์จ ๊ณผ์ ์ค์ ์์ง ํ์ง ๋ชปํ ๋ถ๋ถ์ด์ง๋ง ๊ณต์ ๋๋ฆฝ๋๋ค. ์ ๊ฐ ์ฒ์์ ์์ฑ์์์ ๋ฐ๋ก ํ๋กํผํฐ๋ฅผ ์ ์ธํ๋ฉด์ ์ฒ๋ฆฌํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์์ง ์ด๊ฒ์ ๊ฒ ํด๋ดค์๋๋ฐ์.class LoginDto( @field:NotBlank val loginId: String, @field:NotBlank val password: String, )์ ์ฝ๋๋ฅผ JAVA๋ก ๋ฐ๊ฟ์ ์์ฑ์ ๋ถ๋ถ์ ๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.public LoginDto(@NotNull String loginId, @NotNull String password) { Intrinsics.checkNotNullParameter(loginId, "loginId"); Intrinsics.checkNotNullParameter(password, "password"); super(); this.loginId = loginId; this.password = password; }์ฌ๊ธฐ์ ํ๋์ ๋ฐ์ดํฐ๋ฅผ ๋ด์์ผ Validation ์ฒดํฌ๋ฅผ ํ ํ ๋ฐ ๊ทธ ์ ์ null ์ฒดํฌ๊ฐ ์คํ๋๋ฉด์ Validation ์ฒดํฌ ์ ์ error๋ฅผ ๋จ์ด๋จ๋ฆฝ๋๋ค.Service์์ ํด๋น DTO์ ๊ฐ์ ๋ถ๋ฌ์ฌ๋ null ํ์ฉ๋์ง ์๋ ํ์ ์ผ๋ก ๊ฐ์ ธ์ค๊ธฐ์ํด String์ ์ฐ๋ ์์ฑ์์์ ์ด๋ฏธ ์ฒดํฌ๋ฅผ ํด๋ฒ๋ฆฌ๊ณ error๋ฅผ ๋ฐ์์ํค๋๋ผ๊ตฌ์.๊ทธ๋์ ์ด๋ ๊ฒ ํ๋ ์ ์ด์ DTO์ ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๊ทธ๋์ ๋ง์๋๋ฆฐ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ฒ๋ผ ์ ๋ฌ๋ฐ๋ ๊ฐ์ null ํ์ฉ์ผ๋ก ๋ฐ์ผ๋ฉด์ ํ๋กํผํฐ์ ๋ฃ์ด์ค๋ null์ธ ๊ฒฝ์ฐ default ๊ฐ์ผ๋ก ""์ ๋ฃ์์ต๋๋ค.๊ทธ๋ ๊ฒ ํ๋ฉด JAVA๋ก ๋ณ๊ฒฝํ ์์ฑ์๊ฐ ์๋์ ๊ฐ์ด ๋ง๋ค์ด์ง๋๋ค.public LoginDto(@Nullable String loginId, @Nullable String password) { String var10001 = loginId; if (loginId == null) { var10001 = ""; } this.loginId = var10001; var10001 = password; if (password == null) { var10001 = ""; } this.password = var10001; } ์ ๋ต๋ณ์ด ๋์์ด ๋์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค. ์ดํ ๋ ๊ด์ฐฎ์ ๋ฐฉ๋ฒ ์ฐพ๊ฒ๋๋ฉด ๊ณต์ ๋๋ฆฌ๊ฒ ์ต๋๋ค.๊ฐ์ ๋ด์ฃผ์๊ณ ์ด๋ ๊ฒ ์ง๋ฌธ๊น์ง ์ฃผ์ ์ ๋ค์ ํ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค :)
- 1
- 2
- 674
Q&A
findTop10ByOrderByCntDesc ํจ์์ ๋์ ์๋ฆฌ์ ๋ํ ์ง๋ฌธ
์๋ ํ์ธ์. ๊น์ ํ๋ ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ง๋ฌธํ์ ํจ์(๋ฉ์๋)๋ค์ Query Methods ๋ผ๊ณ ํฉ๋๋ค. ์ด๊ฒ์ Spring Data JPA์ ํฌํจ๋์ด ์๋ ๊ธฐ๋ฅ์ธ๋ฐ์. Repository interface์ ๋ฉ์๋ ๋ช ์ผ๋ก query๋ฅผ ์๋์ผ๋ก ์์ฑํด์ค๋๋ค.fun findTop10ByOrderByCntDesc() :List์ด๋ ๊ฒ ๋์ด์๋ ๋ฉ์๋ ๋ช ์ ์๋์ SQL ๋ง๋ค์ด์ ํธ์ถ ์ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค.select w1_0.word, w1_0.cnt from wordcount w1_0 order by w1_0.cnt desc limit ? Query Methods๋ JPA์์ ์ข ๋ ์ฝ๊ฒ Query๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ด์ฌ์ ์์ฑ ๊ท์น์ด ์์ต๋๋ค.์๋์ ๋ ํผ๋ฐ์ค ํ์ธํ์๋ฉด ์์ฑ๋ฒ ํ์ต ํ์ค ์ ์์ต๋๋ค.https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods ๋ณด์๊ณ ๋ ๊ถ๊ธํ์ ๋ด์ฉ ์์ผ์๋ฉด ์ง๋ฌธ ๋จ๊ฒจ์ฃผ์ธ์ :)
- 0
- 1
- 260