๐ง JPA์ ์์์ฑ ์ํ์ ๋ฐ์ดํฐ Log ์ด์
์ ๋ฌด ์ค ํ ๊ฐ์ง ์ด์๊ฐ ์์๊ณ , JPA์ ์์์ํ์ ๋์์๋ฆฌ์ ๋ํด์ ์์ธํ ์ง๊ณ ๋์ด๊ฐ์ผํ ํ์๊ฐ ์๋ค๊ณ ๋๊ปด ํด๋น ๊ธ์ ์ฐ๊ฒ ๋์๋ค.
์ํฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ ํ์ํ์ ๊ณ์ข์์ก(์์น๊ธ)๊ณผ ์ ๊ธ๋ด์ญ์ ๊ด๋ฆฌํ๋ DB์ ๊ณ์ข ์์ก๊ฐ์ ์ฐจ์ก์ด ๋ฐ์ํ๋ค๋ ์๋ฆผ์ ๋ฐ์๋ค.
๐น ์์น๊ธ ์ฐจ์ก ๋น๊ต Spring Batch ๋ฆฌํํ ๋ง
- ์์ธ์ ์ฐพ๊ธฐ์ํด ์ ํ ์ ๋ฌธ์ ์๋ logํ ์ด๋ธ๊ณผ, ํ์ ์ ๊ธ๋ด์ญ logํ ์ด๋ธ์ ๋น๊ตํ์๋ค.
- ์ด๋, ์ ํDB ์๋ ๊ฐ์ ๊ธ์ก์ ์ค๋ณต log๊ฐ ์์ผ๋, ์ ๊ธ ๋ด์ญ DB์๋ ์ฐจ์ก๋งํผ์ ์ค๋ณต ์ ๊ธ log๋ฅผ ๋ฐ๊ฒฌํ ์ ์์๋ค.
์ฐจ์ก์ด 138๋ง์ ๋ฐ์ํ๋ค๊ณ ๊ฐ์ ํ์ ๋,
๋ณดํต์ ์ํฉ์ด๋ผ๋ฉด, ๋์ผํ(id๊ฐ ๋์ผ) ์ ๋ฌธ์ ๋ฐ์ DB์ insert๋๋ค๋ฉด SQL Exception์ด ํฐ์ก์ ๊ฒ์ด๋ผ ์๊ฐํ์๋ค. ํ์ง๋ง ์ํฉ์ผ๋ก ๋ฏธ๋ฃจ์ด ๋ณผ๋, insert๊ฐ ์๋ update๊ฐ ๋์ํ์ ๊ฒ์ผ๋ก ์์ํ ์ ์๋ค.
ํธ๋ ์ ์ ์ด ์ข ๋ฃ๋ ์ดํ(commit)์์๋ ๊ธฐ์กด์ id๋ฅผ ๊ธฐ์ตํ์ฌ update๋ฅผ ํ ์ ์์๋ ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
์์์ํ์ ๊ดํ ๊ด๋ จ๋ ๋ ๋ค๋ฅธ ์ด์.
์์์ฑ ์ปจํ ์คํธ์ ๋ํ ์ค๋ช .
save()
ํ์ฌ persist()
๋ฅผ ์ํํ์ ๋, DB์ ์ด๋ฏธ ๋์ผํ ID(PK)๊ฐ ์๋ค๋ฉด ์์ธ๋ฅผ ๋ฐ์์ํจ๋ค.@Autowired
private EntityManager em;
@Test
@Transactional
void MemberPersistenceTest() {
// 1) ์ ์ํฐํฐ ์ธ์คํด์ค ์์ฑ โ Transient ์ํ
HfMarketingCode testcode = new HfMarketingCode();
testcode.setHitCode("testCode1");
testcode.setCodeName("testName1");
em.persist(testcode);
em.flush();
}
์์์ฑ ์ปจํ
์คํธ์ ๋ฑ๋กํ ๊ฐ์ฒด์ id ์ค์ ์ @GeneratedValue(strategy = GenerationType.IDENTITY)
์ฌ๋ถ์ ๋ฐ๋ผ ์ฃผ์ํด์ผ ํ ์ฌํญ์ด ์๋ค.
persist()
๋ฅผ ์ํํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋ค. ๊ทธ ์ด์ ๋, ๋ช
์์ ์ผ๋กid๋ฅผ ์ง์ ํ๋ ์๊ฐ non-null์ id๊ฐ์ ๊ฐ๊ฒ๋๊ณ , isNew()
์ ์ฒซ ํธ์ถ๋ถํฐ id๊ฐ null์ด ์๋๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด์ ์กด์ฌํ๋ id๊ฐ์ ๋ํด persist๋ฅผ ์ํํ๊ฒ ๋์ด ์์ธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๋ค.์๋๋ JPA save()์ isNew() ๋ถ๊ธฐ๋ฌธ
@Transactional
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null.");
if (this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return this.em.merge(entity);
}
}
๋์ผํ idx(pk)์ ์ํฐํฐ๋ฅผ ๋๊ฒจ save๋์์ ์ํํ์ ๋, persist(insert) ๊ฐ ์๋ merge(update) ๊ฐ ๋์๋ค๋ฉด,
ํด๋น ์ํฐํฐ์ ์์ ์ํ๋ ์ด๋ป๊ฒ ๋๋๊ฐ?
์ํฐํฐ ๋ฉ๋์ ๋ ํธ๋ ์ ์ ์ด ์ข ๋ฃ๋ ๋ close๋๋ฉฐ, ์ด๋ ๋ชจ๋ ์์์ ์ปจํ ์คํธ์ ๋ฑ๋ก๋ ์ํฐํฐ๋ฅผ ์ค์์ ์ํ๋ก ๋๋ฆฐ๋ค. ๋ฐ๋ผ์, ์ค์์ ์ํ๋ก ๊ด๋ฆฌ๋๊ณ ์๋ ๊ฐ์ฒด์ save() ์ฐ์ฐ์ด ์ํ๋๋ฉด์, update์ฟผ๋ฆฌ๊ฐ ์คํ๋ ๊ฒ.
๊ทธ๋ ๋ค๋ฉด ์ค์์ ์ํ์ ์ง์ ๋ฒ์๋ ์ด๋ป๊ฒ ๋ ๊น?
์์์ ๋ค์๊ณผ ๊ฐ์ด ํํํ ๋ถ๋ถ์ด ์๋ค. ์ด๋ ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์๊ฒ ๋์๋ค..
โ ๋น์์ ์ํ์ ์ํฐํฐ๋ฅผ
save()
ํ์ฌpersist()
๋ฅผ ์ํํ์ ๋,DB์ ์ด๋ฏธ ๋์ผํ ID(PK)๊ฐ ์๋ค๋ฉด ์์ธ๋ฅผ ๋ฐ์์ํจ๋ค โ
๋ฌผ๋ก , ์ด๋ฏธ ์กด์ฌํ๋ id๊ฐ์ ๊ฐ๋ ์ํฐํฐ๋ฅผ persist()
ํ๋ฉด pk์ค๋ณต ์์ธ๊ฐ ๋ฐฉ์ํ๋ ๊ฒ์ ๋ง๋ค. persist()
๋ ์์์ฑ ์ปจํ
์คํธ์ ๋ฑ๋ก์ฌ๋ถ๋ฅผ ํ๋จ ํ ๋ฟ, id๊ฐ์ ์ ๋ฎค๋ฅผ ๋ฐ์ง์ง(selectํ์ง) ์๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง ์ด๋ฌํ ์ํฉ์ด ๋ฐ์ํ๋ ๊ฒ์ด ์ ์์ ์ธ ์ํฉ์์ ๋ถ๊ฐ๋ฅํ๋ค.
๊ทธ ์ด์ ์ ๋ํด์ ์ค๋ช ํ๊ฒ ๋ค.
: Assigned(์ฌ์ฉ์ id ์ง์ ์ง์ ) ์ ๋ต์ผ ๋, id == null or 0
์ผ๋๋ง โ์ ์ํฐํฐ๋ก์จ ํ๋จํ๋ค.โ
public boolean isNew(T entity) {
ID id = this.getId(entity);
Class<ID> idType = this.getIdType();
if (!idType.isPrimitive()) {
return id == null; //null ์ด๊ฑฐ๋,
} else if (id instanceof Number) {
return ((Number)id).longValue() == 0L; //0 ์ผ๋๋ง ์๋ก์ด ๊ฐ์ฒด๋ก ํ๋จ
} else {
throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType));
}
}
ํ์ง๋ง ์ด๋, Assigned์ผ๋ก ์ง์ id์ ๊ฐ์ ์ดํ๋ฆฌ์ผ์ด์
์์ ์ง์ ์ง์ ํ๋ค๋ฉด, (id๊ฐ์ ํฌํจํ ์ํฐํฐ)
persist()
๊ฐ ์๋ merge()
๋ก ๋์ด๊ฐ ์๋ฐ์์๊ฒ ๋๋ค๋ ๊ฒ์ด๋ค.
persist()
๊ฐ ๋์๋์ด PK์ค๋ณต ์์ธ๊ฐ ๋ฐ์ํ ์ผ์ ์๋ค๋ ๊ฒ์ด๋ค.: JPA์ save()๋ ๋จ์ํ insert์ update์ ํตํฉ์ด ์๋๋ค. ๊ฐ ๋์์ ์๋ฆฌ์ ํน์ฑ์ ํ์ ํ์ฌ ์์ธ์ฌํญ์ ์ ํํ ํ๋จํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์์ ๊ฐ๋ฅํ๋๋ก ์ค๊ณํด์ผํ๋ค.