Spring의 다양한 어노테이션들

Kim Dong Kyun·2023년 8월 21일
1
post-thumbnail

1. Accesors(chain = true) - Lombok

  • 게터, 세터등을 .set~ .set~ 이렇게 라인별로 사용하게 하는 것이 아닌

  • @Builder 처럼 사용 가능하게 해준다.

    Foo foo = new Foo();
    
                foo.setAccount(account)
                    .setPassword(password)
                    ...
                 
  • 그렇게 매력적이진 않은 듯 하다...

2. implements Persistable - Entity 단에 사용

  • @GeneratedValue 는 아이디를 관리 할 때 자동 생성되는 값으로 주입시킨다

  • 그리고 해당 작업은 엔티티의 save 시 영속성 컨텍스트가 플러쉬 될 때 일어난다. 즉 이 전까지는 아이디가 없다 (식별자가 없다) [Jdbc를 사용해서 벌크인서트 예시]

그리고

SPRING + JPA 의 save 시 기본 동작은 다음과 같다

  1. 식별자가 존재하지 않으면 (자동 생성하는 값이라, 식별할 녀석이 없으면) persist

  2. 식별자가 존재하면 (임의로 id 값을 생성하면) merge

여기서 merge의 동작 순서는, DB에서 식별자가 존재하는 지 확인 후(조회), 있으면 update, 없으면 insert 가 일어난다. 즉, 비효율적이다

그러므로 id를 임의로 생성하는 방식에서는 이 부분에 대한 핸들이 필요하다. 이것을 위해 implemet 하는 녀석이 Persistable< idType > 이다.

훌륭하신 선생님의 블로그

  • 요약하자면 위의 설명(식별자 관련)과 더해서

  • 새 엔티티를 넣을 때 식별자를 사용하지 않도록 설정해주는 녀석이 저녀석

  • 자동 생성 전략의 경우, id를 WrapperType(Long, Integer ...)으로 사용하는 경우에는 null값이어야만 식별자가 존재하지 않음으로 판별하며

  • primitiveType중 Number 타입(int, long)등은 초기값이 0이어야 식별자가 존재하지 않음으로 판단한다.

  • 이 판별 로직은 isNew() 라는 이름으로 구현되어 있는데, (스프링 내부, JpaPersistableEntityInformation)

  • 해당 로직을 오버라이드 해서 재정의해주는 작업으로, 우리는 새로운 엔티티로 판별시켜 merge가 일어나지 않게 할 수 있다.

@Entity
@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item implements Persistable<String> {

 	@Id
	private String id;
 
	@CreatedDate
 	private LocalDateTime createdDate;
	 
 	public Item(String id) {
            this.id = id;
 	}
 
 
 
 	@Override
 	public String getId() {
            return id;
 	}
 
 	@Override
 	public boolean isNew() {
            return createdDate == null;
 	}
}
  • 위와 같은 형태로 isNew를 오버라이드

  • 생성 시간에 따라 판별하면 편리하다


@DynamicUpdate

선생님 블로그

  • 현재 소스에서 가장 의문이 드는 녀석

  • "저것을 사용한다 == 설계의 오류다" 라던 우아한 테크의 블로그 글이 떠오른다...

  • JPA에서 엔티티를 업데이트 할 때, 명시적인 .update() 매서드를 통한 업데이트 외에도

  • 영속성 컨텍스트의 더티 체크를 통한 업데이트가 가능하다 (그리고 이게 더 많이 쓰이는 듯 하다)

  • 이 컨텍스트의 판별 로직으로써 기존에는 beforeEntity.equals(afterEntity) 와 같은 형식으로 진행이 된다면

  • 저 어노테이션을 달게 되면 feild1.equals.....fieldN.equals() 만큼의 판별이 필요하다 (jpa 입장에서) (즉, 다른 매서드 상에서도 손해가 발생한다. 더티 체킹은 항상 일어나니까(스냅샷 비교))

  • 더불어서 JPA는 내부적으로 JDBC와 PreparedStatement 를 통해서 SQL 구문을 캐싱 하는데, 위와 같이 사용하게 된다면 이 캐시의 히트율이 떨어진다.


@DynamicInsert

  • 얘는 진짜로 처음봤다

  • insert 시에 null이 아닌 컬럼만 스캔하여 insert문이 발생하도록 해주는 녀석

결론 : 소스를 보면서 의도를 좀 더 파악해보자!

0개의 댓글