๐ง 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์ ํตํฉ์ด ์๋๋ค. ๊ฐ ๋์์ ์๋ฆฌ์ ํน์ฑ์ ํ์ ํ์ฌ ์์ธ์ฌํญ์ ์ ํํ ํ๋จํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ์์ ๊ฐ๋ฅํ๋๋ก ์ค๊ณํด์ผํ๋ค.