JPA์ save(), saveAll(), saveAllAndFlush() ๋ฉ์๋๋ค์ ์์์ฑ ์ปจํ ์คํธ ๊ฐ๋ ๊ณผ ํจ๊ป ํจ์จ๊ณผ ์ฑ๋ฅ์ ๋ํ ์ฐจ์ด๋ฅผ ์์๋ณด๊ฒ ๋ค.
1. save()
๋จ๊ฑด ์ํฐํฐ๋ฅผ ์ ์ฅํ๋๋ฐ ์ฌ์ฉ๋๋ค.
@Transactional
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (entityInformation.isNew(entity)) {
entityManager.persist(entity);
return entity;
} else {
return entityManager.merge(entity);
}
}
๋จผ์ isNew() ๋ฉ์๋๋ฅผ ํตํด ์ํฐํฐ์ ๊ธฐ๋ณธ ํค ๊ฐ์ ํตํด ์๋ก์ด ์ํฐํฐ์ธ์ง ๊ฒ์ฌํ๋ค.
public boolean isNew(T entity) {
//...
return id ==null;
}
๊ตฌ์ฒด์ ์ผ๋ก ์ดํด๋ณด๋ฉด id๊ฐ null์ธ์ง๋ฅผ ํตํด ์์์ฑ ์ปจํ ์คํธ์ ์กด์ฌํ๋์ง ํ์ธํ๋ค.
id๊ฐ null์ด๋ผ๋ฉด em.persist()๋ฅผ, null์ด ์๋๋ผ๋ฉด em.merge()๋ฅผ ์คํํ๊ฒ ๋๋ค.
์ฆ,
1. ๋ง์ฝ ์๋ก์ด ์ํฐํฐ(New, ๋น์์ ์ํ)๋ผ๋ฉด ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅํ๋ค. (persist)
2. ๊ธฐ์กด์ ์กด์ฌํ๋ ์ํฐํฐ์ผ ๊ฒฝ์ฐ, Detached ์ํ์ ์ํฐํฐ๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ๋ฐ์ํ๋ค. (merge)
๋ผ์ดํ ์ฌ์ดํด์ ๊ธฐ๋ณธ์ ์ธ ๋ด์ฉ์ด๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์์ save()๋ฅผ ํตํด Entity๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ๋ณด๊ดํด๋๊ณ , ํธ๋์ญ์ ์ด ๋ชจ๋ ์ข ๋ฃ๋๋ฉด
commit ์ด ํธ์ถ ๋ ๋ flush()๊ฐ ๋ฐ์ํ๋ฉด์ DB์ ์ ์ฅ๋๋ค.
1-1. save() ์ ๋ฆฌ์์ค ๋ญ๋น?
save() ๋ฉ์๋ ๋ด์์๋ ์ค์ SQL ์ฟผ๋ฆฌ๋ฌธ์ ์คํํ๊ธฐ ์ ์ INSERT ๋ช ๋ น์ ํ ๊ฒ์ธ์ง, UPDATE ๋ช ๋ น์ ํ ๊ฒ์ธ์ง ๋๋๊ฒ ๋๋ ๋ถ๊ธฐ์ ์ด ์กด์ฌํ๋ค.
์ ๋ด์ฉ๊ณผ ๊ฐ์ด ์ํฐํฐ์ ์ํ๋ฅผ ํตํด ๊ฒฐ์ ํ๊ฒ ๋๋๋ฐ, ์ด๋ฅผ ์ํด์ save() ๋ฉ์๋์์๋ ์กฐํ๊ฐ ์ผ์ด๋๊ฒ ๋๋ค.
๋ฐ๋ผ์, ํธ๋์ญ์ ์ด ์ ์ง๋๋ ์ํ์ผ ๋ ์ํฐํฐ ์์ ํ save() ๋ฉ์๋๋ ๋ฆฌ์์ค ๋ญ๋น๊ฐ ๋ ์ ์๋ค.
์์ 1)
public void createUser(String name) {
User user = User.builder()
.name(name)
.build();
userRepository.save(user); //์กฐํ 1 + ์ฝ์
1
}
์ ์ฝ๋์์ ์๋ก์ด ์ํฐํฐ(New) ์ด๋ฏ๋ก,
save() ๋ฉ์๋๊ฐ ์คํ๋๋ ์๊ฐ ์๋ก์ด ์ํฐํฐ์ธ์ง ๊ฒ์ฌ(์กฐํ 1๋ฒ)ํ๊ณ , ํธ๋์ญ์ ์ด ๋ชจ๋ ๋๋๋ฉด INSERT ์ฟผ๋ฆฌ๋ฌธ์ด ์คํ ๋ ๊ฒ์ด๋ค.
์์ 2)
@Transactional
public void updateUser(Long id, String name){
User user = userRepository.findById(id); //์กฐํ 1
user.setName("ํ๊ธธ๋");
userRepository.save(user); //์กฐํ 1 + ์
๋ฐ์ดํธ 1
//ํธ๋์ญ์
์ด ๋ชจ๋ ๋๋๋ฉด ๋ณ๊ฒฝ๋ ํ๋๋ฅผ ์๋์ผ๋ก DB์ commit
}
์ user๋ ์ด๋ฏธ id๋ฅผ ๊ฐ์ง๊ณ ์๋ ์์์ฑ ์ํฐํฐ์ด๋ค.
๋ง์ง๋ง์ save() ๋ฉ์๋๋ฅผ ํตํด ๋ถํ์ํ ์กฐํ 1๋ฒ์ด ์ผ์ด๋๊ณ , UPDATE ์ฟผ๋ฆฌ๋ฌธ์ด ์คํ ๋ ๊ฒ์ด๋ค.
ํธ๋์ญ์ ์ด ๋ชจ๋ ์ข ๋ฃ๋๋ฉด, ๋ณ๊ฒฝ๋ ํ๋๋ฅผ ์๋์ผ๋ก ๊ฐ์งํ์ฌ commit ๋๋ฏ๋ก, ๋ถํ์ํ ์กฐํ๋ฅผ ํ ํ์๊ฐ ์๋ค.
@Transactional
public void updateUser(Long id, String name){
User user = userRepository.findById(id); //์กฐํ 1
user.setName("ํ๊ธธ๋");
//ํธ๋์ญ์
์ด ๋ชจ๋ ๋๋๋ฉด ๋ณ๊ฒฝ๋ ํ๋๋ฅผ ์๋์ผ๋ก DB์ commit
}
2. saveAll()
์ฌ๋ฌ ์ํฐํฐ๋ฅผ ์ผ๊ด ์ ์ฅํ ๋ ์ฌ์ฉ๋๋ค.
@Transactional
@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "Entities must not be null");
List<S> result = new ArrayList<>();
for (S entity : entities) {
result.add(save(entity));
}
return result;
}
๋จ์ ๋ฐ๋ณต๋ฌธ์ ์ด์ฉํด save() ๋ฉ์๋๋ฅผ ์ฌ๋ฌ๋ฒ ์ฌ์ฉํ ๊ฒ๊ณผ ๊ฐ๋ค.
ํ์ง๋ง, ๋ถ๋ช ํ ์๋น์ค๋จ์์ save()๋ฅผ ์ฌ๋ฌ๋ฒ ํธ์ถํ๋ ๊ฒ๊ณผ saveAll()์ ํตํด ์ผ๊ด์ฒ๋ฆฌ ํ๋ ๊ฒ์ ๋ถ๋ช ํ ์ฐจ์ด๊ฐ ์๋ค.
saveAll()์ ์์์ ๋ณด๋ค์ํผ ํ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์ฌ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก JpaRepository๋ฅผ ์์ํ ํด๋์ค๋ ํ๋ก์ ๊ฐ์ฒด๊ฐ ๋น์ผ๋ก ๋ฑ๋ก๋์ด ์ฌ์ฉ๋๋ค. (class com.sun.proxy.$ProxyXXX)
save()๋ฅผ ์ฌ๋ฌ๋ฒ ํธ์ถํ๊ฒ ๋๋ฉด ํธ์ถ๋ง ๋งํผ ํด๋น ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํ๊ฒ๋๊ณ ,
savAll()๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด ํด๋น ํ๋ก์ ๊ฐ์ฒด๋ฅผ ํ ๋ฒ๋ง ํ๊ณ save()๋ฅผ ๋ด๋ถ ํจ์๋ก ํธ์ถํ๊ธฐ ๋๋ฌธ์
์ฌ๋ฌ๋ฒ์ save() ํธ์ถ๋ณด๋ค saveAll() ํธ์ถ ํ ๋ฒ์ด ๋ ํจ์จ์ ์ด๋ค.
3.saveAllAndFlush()
@Transactional
@Override
public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
List<S> result = saveAll(entities);
flush();
return result;
}
saveAllAndFlush()๋ saveAll()์ ํธ์ถํ๊ณ ๊ฐ์ ๋ก flushํ๋ค.
์์์ฑ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ ํ ๋ค์ ๋ก์ง์์ ์์ํ ๋ ์ํ๋ฅผ DB์์ ํ์ธํด์ผ ํ๊ฑฐ๋, ํ ์คํธ & ๋๋ฒ๊น ์ฉ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ์ง๋ง
๋ํฐ ์ฒดํน์ ํ์ํ ์ฐ์ฐ์ด ์ถ๊ฐ์ ์ผ๋ก ๋ฐ์๋๊ณ , DB ์ปค๋ฐ ์ ์ด๊ธฐ ๋๋ฌธ์ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๋ค.
์ฐธ๊ณ
https://docs.spring.io/spring-data/jpa/reference/repositories/core-concepts.html
https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https://blog.kakaocdn.net/dn/b6Csm8/btrR8yFlZvk/9JK0yUkShKwgIBTFTwAvak/img.png
https://pingpongdev.tistory.com/25
'BackEnd > Spring Boot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Spring Event๋ก ํธ๋์ญ์ , ์์กด์ฑ ๋ถ๋ฆฌํ๊ธฐ (0) | 2024.08.11 |
---|---|
JPA/Hibernate Exception๋ค๊ณผ ์์ธ ์ฒ๋ฆฌ (0) | 2024.08.04 |
[Spring] REST API ์นด์นด์ค ๋ก๊ทธ์ธ ๊ตฌํํ๊ธฐ (5) | 2024.05.20 |
[Spring] CORS ๊ฐ๋ ๊ณผ Spring Security 6 ์ค์ ํบ์๋ณด๊ธฐ (0) | 2024.05.19 |
[ Spring ] Spring Data Redis (0) | 2024.04.14 |