Spring Data Jdbc의 save 방식과 Auditing

디디·2020년 8월 16일
2

Spring Data Jdbc

목록 보기
1/2

Spring Data Jdbc의 Save 방식

Spring Data Jdbc의 Save는 기본적으로 ID가 있는 Entity 객체에 대해선 Update를 수행하고 ID가 없는 Entity에 대해선 INSERT를 수행합니다. 이게 어떻게 동작하는 걸까요?

위 메서드는 CrudRepository가 사용하는 JdbcAggregateTemplate 입니다.
MappingContext에서 Save요청으로 들어온 인스턴스를 꺼내, isNew항목에 따라 체크하여 create또는 update를 수행합니다.

Id가 있는 Entity 저장

저는 ID가 있는 경우에도 Save를 하기 위해 Insert 인터페이스를 만들어서 사용하기로 했습니다.

제가 Insert하고 싶었던 엔티티는 대략 다음과 같습니다.

해당 엔티티 객체에 아이디를 넣고 생성하려던 찰나, 다음과 같은 에러가 터지더군요.

CREATED_AT 칼럼은 분명히 Auditing을 통해 자동 주입 될텐데 어째서 null이 나오는 걸까요? 해당 문제의 범인을 찾기위해 열심히 Call Stack을 뒤져보던 찰나 이런 녀석을 발견했습니다.

entity의 isNew 값이 true가 아니면 Created라고 판단하지 않아 createdAt 값이 Auditing되지 않은 것이 였습니다. 그렇다면 이 isNew 값은 어떻게 설정되는 걸까요?


PersistentEntityIsNewStrategy 클래스에서 이 값을 설정하는 전략을 선택하는데, 간단히 요약하자면, 엔티티 필드에 @Version 값 또는 @Id 값을 확인하여, 그 값이 0 또는 null이면 isNew가 true로 나오는 방식입니다.

따라서 id가 null이 아니라면, isNew는 항상 false가 나와, save를 해도 update가 수행되고, @createdDate auditing도 정상적으로 이루어지지 않는 것입니다.

해당 문제를 해결하기 위해, WithInsert가 아닌, Persistable을 implement하는 방식으로 다시 구현을 해보았습니다.

Persistable을 통해 isNew를 직접 Setting 해준다면, 원하는 아이디로 저장이 가능합니다. Auditing 또한 정상적으로 동작하죠. 하지만, 저장 이후에 isNew를 false로 초기화 해주기 위해선 라이프사이클 이벤트나 콜백을 통해 제어해주어야 되는 번거로움이 있겠네요.

이 방법 이외에 라이프사이클 이벤트를 통해 원하는 아이디를 주입해주는 방법과 @Version을 사용하는 방법도 있습니다. 다음 글에선 라이프사이클 이벤트를 다뤄보고 싶네요

마치며

Spring Data Jdbc는 공부할수록 매력적인 프레임 워크인 것 같아요. 단순하고 직관적이죠. 하지만 항상 이렇게 생각하고 쉽게 접근하려다가 딜레마에 빠진 경우가 많은 것 같아요. 아직도 Spring Data Jdbc에 적응하진 못했나 봅니다 😭 공부를 충분히 하고나서 훗날 많은 성장을 이룬다면, Data JPA와 Data JDBC를 비교해보는 글을 써보고 싶네요.
긴 글 읽어주셔서 감사합니다😊

profile
식빵 고양이 디디

0개의 댓글