๐ 3/11(์) ๋ด์ผ๋ฐฐ์์บ ํ Java-Spring 52์ผ์ฐจ TIL - SpringData JPA ๋ค์ด๋ด๋ฏน ์ฌ์ฉํ๊ธฐ / @DynamicInsert์ @DynamicUpdate๋?
๐ ์ค๋์ ํ์ต ํค์๋
- SpringData JPA - @DynamicInsert
- SpringData JPA - @DynamicUpdate
๐ @DynamicInsert, @DynamicUpdate๋?
@DynamicInsert์ @DynamicUpdate๋ Hibernate์์ ์ ๊ณตํ๋ ์ฃผ์(Annotation)์ผ๋ก, ์ํฐํฐ์ ์ ์ฅ ๋ฐ ์์ ๋์์ ๋ํ ์ฑ๋ฅ ๋ฐ ์ต์ ํ๋ฅผ ์ํด ์ฌ์ฉ๋๋ค. JPA์์ ์ํฐํฐ์ ์ ์ฅ(insert) ๋ฐ ์ ๋ฐ์ดํธ(update) ์ ์ํฐํฐ์ ๋ณํ๊ฐ ์๋ ์ปฌ๋ผ์ ๋ํด์๋ง SQL์ ์คํํ๊ณ , ๋ณํ๊ฐ ์๋ ์ปฌ๋ผ์ ๋ํด์๋ ์คํํ์ง ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค. ํ๋๊ฐ ๋ง์์ง์๋ก ์ฑ๋ฅ์ ์ฐจ์ด๊ฐ ๋ ๋ง์ด ๋ํ๋ ์ ์๋ค.
@DynamicInsert : ์ํฐํฐ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฝ์ (INSERT)ํ ๋, ๋์ด ์๋ ์์ฑ๋ง์ ๋์์ผ๋ก ํ๋ ๋์ INSERT ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค. INSERT๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ถํ์ํ ์ปฌ๋ผ์ ์ ์ธํ๊ณ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ฏ๋ก, ์ฝ์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค.
@DynamicUpdate: ์ํฐํฐ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์์ (UPDATE)ํ ๋, ๋ณ๊ฒฝ๋ ์์ฑ๋ง์ ๋์์ผ๋ก ํ๋ ๋์ UPDATE ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค. ๋ณ๊ฒฝ๋ ์์ฑ๋ง์ ๋์์ผ๋ก ํ๋ ๋์ UPDATE๋ ๋ถํ์ํ ์ปฌ๋ผ์ ์ ๋ฐ์ดํธํ์ง ์์ผ๋ฏ๋ก, ์์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ค.
๐ @DynamicInsert ์ฌ์ฉํด๋ณด๊ธฐ
User ํด๋์ค๋ฅผ ๋ง๋ค์ด์ ์ด๋ค ์์ผ๋ก ์ฟผ๋ฆฌ๊ฐ ๋ ์๊ฐ๋์ง ํ์ธ์ ํด๋ณด์.
@DynamicInsert
@Entity
@Table
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id @GenerateValue
@Column
private Long id;
@Column
private String username;
@Column
private String password;
}
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด์.
@Test
void dynamicInsertTest() {
// given
var newUser = User.builder().username("user").build();
// when
userRepository.save(newUser);
// then
// ๋ถ๋ถ ์์ฑ ์ฟผ๋ฆฌ
}
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ๊ฐ ์ด๋ค ์์ผ๋ก ๋ ์๊ฐ๋์ง ํ์ธํด ๋ณด์.
@DynamicInsert ์ ์ฉ ์ , ํ๋ฅผ ๋น๊ตํด ๋ณด๋ฉด ๋ง์ ์ฐจ์ด๊ฐ ๋์ง ์์ง๋ง ํ๋๊ฐ ๋ง์์ง์๋ก ๋ ์ฐจ์ด๊ฐ ๋ง์ด ๋๊ฒ ๋๋ค.
๐ @DynamicUpdate ์ฌ์ฉํด ๋ณด๊ธฐ
User ํด๋์ค๋ฅผ ๋ง๋ค์ด์ ์ด๋ค ์์ผ๋ก ์ฟผ๋ฆฌ๊ฐ ๋ ์๊ฐ๋์ง ํ์ธ์ ํด๋ณด์.
@DynamicUpdate
@Entity
@Table
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id @GenerateValue
@Column
private Long id;
@Column
private String username;
@Column
private String password;
}
ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด์.
@Test
void dynamicUpdateTest() {
// given
var newUser = User.builder().username("user").password("password").build();
userRepository.save(newUser);
// when
newUser.updatePassword("new password");
userRepository.save(newUser);
// then
// ๋ถ๋ถ ์์ ์ฟผ๋ฆฌ
}
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ๊ฐ ์ด๋ค ์์ผ๋ก ๋ ์๊ฐ๋์ง ํ์ธํด ๋ณด์.
@DynamicUpdate ์ ์ฉ ์ , ํ๋ฅผ ๋น๊ตํด ๋ณด๋ฉด ๋ง์ ์ฐจ์ด๊ฐ ๋์ง ์์ง๋ง ํ๋๊ฐ ๋ง์์ง์๋ก ๋ ์ฐจ์ด๊ฐ ๋ง์ด ๋๊ฒ ๋๋ค.
- ์ฌ์ฉ ์ ๊ณ ๋ คํด์ผ ํ ๊ฒ -
๋ค์ด๋ด๋ฏน ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ์ค๋ ์ท(Snapshot)์ ์ฌ์ฉํ์ง ์๊ณ , ์ํฐํฐ์ ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ํ์ธํ์ง ์๊ณ ๋ ์ฟผ๋ฆฌ๊ฐ ์์ฑ๋๋ค. ๋ณ๊ฒฝ๋ ํ๋๋ฅผ ๋ฐ๋ก ์ถ์ ํ์ง ์๊ณ ๋ ์ํฐํฐ์ ๋ชจ๋ ํ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋์ ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
์ด๋ฐ ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ํ์ํ ํ๋๋ง์ ๋์์ผ๋ก ํ๋ ๋์ ์ธ ์ฟผ๋ฆฌ๊ฐ ์์ฑ๋์ด, ๋ถํ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ์ค์ผ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด์ ์ฃผ์ํ ์ ์ ๋ณ๊ฒฝ ๊ฐ์ง๊ฐ ์ถฉ๋ถํ ์ด๋ฃจ์ด์ง์ง ์์ ์์์ฑ ์ฝํ ์คํธ์ ์ํ๊ฐ ์ ํํ๊ฒ ์ ์ง๋์ง ์์ ์ ์๋ค๋ ๊ฒ์ด๋ค. ๋ณ๊ฒฝ ๊ฐ์ง๋ฅผ ํตํ ์ํฐํฐ์ ์ผ๊ด์ฑ ์ ์ง๊ฐ ์ค์ํ ๊ฒฝ์ฐ์๋ ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํ๋ค.
์์์ฑ ์ปจํ ์คํธ(Persistence Context)๋ ์ํฐํฐ์ ์ํ๋ฅผ ์ถ์ ํ๊ณ , ์ค๋ ์์ ์ฌ์ฉํ์ฌ ์ํฐํฐ์ ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ค. ๋ณ๊ฒฝ๋ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค ๋๊ธฐํ๋๋ค.
์ฆ, ์์์ฑ ์ปจํ ์คํธ๋ ์ค๋ ์ท์ ์ฌ์ฉํ์ฌ ์ํฐํฐ์ ๋ณ๊ฒฝ ์ฌ๋ถ๋ฅผ ๊ฐ์งํ๊ณ , ๋ณ๊ฒฝ๋ ๋ด์ฉ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๊ธฐํํ๋ค. ์ด๋ฅผ ํตํด ํธ๋์ญ์ ์ด๋ Flush ์์ ์์ ๋ณ๊ฒฝ๋ ํ๋๋ง์ ๋์์ผ๋ก ํ๋ ํจ์จ์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ผ๊ด๋ ์ํ๋ฅผ ์ ์งํ ์ ์๋ค.
ํ์ง๋ง, ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ง ์์๋ JPA์ ๊ธฐ๋ณธ ๋์์๋ ๋ฌธ์ ๊ฐ ์์ผ๋ฉฐ, ์ค๋ฌด์์๋ ๊ฐ๋ฐ์์ ํธ์์ ์ฑ๋ฅ ์ต์ ํ ์ธก๋ฉด์์ ์ฌ์ฉ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋๋ค. ๋ฐ๋ผ์ @DynamicInsert์ @DynamicUpdate์ ์ฌ์ฉ ์ ๋ฌด๋ ๊ฐ์ธ๋ณ๋ก ์ํฉ์ ๋ง๊ฒ ๊ฒฐ์ ํ๋ฉด ๋๋ค.