@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> ... {
@Transactional
public <S extend T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
}
대충 스프링 데이터 JPA 구조는
전체적으로 @Transactional(readOnly = true)를 이용해 읽기 전용으로 설정한 뒤에,
저장을하는 메서드가 나오면 메서드에 @Transactional을 넣어 우선순위를 주는 구조로 짜여있음.
참고로 트랜잭션 옵션에 readOnly = true 설정을 하면 트랜잭션 끝날때 flush를 생략하여 약간의 성능 향상을 얻을 수 있음
save() 메서드
persist)merge)이전 강의 내용을 떠올려 보면,
머지를 사용할때 업데이트가 아니고 덮어씌우기이므로,
비어있는 부분을 다 새롭게 덮어버린다.
취약한 단점은 DB 설렉터를 호출하여 데이터를 가져온다는 점이다.
머지를 데이터 업데이트 용으로 사용하는 것은 좋지 않은 방법.
새로운 엔티티를 판단하는 기준
null로 판단0으로 판단Persistable 인터페이스를 구현해서 판단 로직 변경 가능
이 경우에 Item 객체에서 id가 null이면 새 엔티티,
값이 있으면 이미 있는 엔티티로 구분한다.
하지만, 이 아이디를 다른 형태로 값을 넣어서 받도록 구조를 짠다면,
비효율적인 로직이 발생되는데,

만약에 이상한 아이디 값을 넣어버린 상태로 save()를 하게 되면,
null이 아니므로 머지를 하게 된다.
그러면 select문을 통해 DB에서 값을 찾게 되지만, 해당하는 아이디는 없으므로 그 후에 새롭게 저장하게 된다.
물론 평소에는 @GenerateValue를 이용해
자동으로 할당해주는 방식을 많이 사용하기 때문에
상관없지만, 나중에는 @Id만 이용해서 직접 할당으로 방식을 바꾼다던지,
임시로 값을 설정해야하는 상황이 있을때가 있다.
그럴때 위와 같은 상황을 피하고 좋은 로직을 만들기 위해서는
판단 기준을 내가 설정해야한다.

Persistable<String>
@EntityListeners(AuditingEntityListener.calss)를 추가해야한다.isNew()를 구현해야한다.
그럼 이 부분에서 createdDate를 판단 기준으로 바꾸기 때문에,
persist()로 진행하는 것을 확인할 수 있다.