반응형
문제
특정 데이터를 관리할 때. 두 가지 방식으로 PK 를 관리한다.
1. auto increase 되는 숫자를 PK 로 사용한다.
2. loginId, 주민번호, 식별 코드 등등 중복되지 않는 유일한 값을 PK 로 사용한다.
두 번째 방식으로 save() 로 새롭게 데이터를 저장할 경우 실행되는 쿼리는 insert 만 실행되길 기대하지만, 데이터를 조회하는 select 가 저장 할 때마다 계속 실행되는 문제가 생겼다.
해결
@Transactional
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null.");
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
save() 는 특정 값을 통해 분기처리하고, 업데이트와 저장 두 가지의 역할을 수행한다. ID 가 있는 경우에는 업데이트, 없는 경우에는 저장을 수행하는데. 위의 두 번째 방식으로 진행할 경우 ID 를 직접 부여한 상태로 save() 를 실행하기 때문에 ID 가 존재하기 때문에 업데이트 수행하고, 업데이트 할 데이터를 조회한다. insert 만 실행되길 원한다면 분기처리하는 특정값을 오버라이딩 해주면 된다.
1. isNew() 함수 오버라이딩
- Persistable 인터페이스를 문제의 엔티티에 구현하고, isNew() 함수를 오버라이딩 하면 된다. isNew() 함수의 결과에 따라서 업데이트 할지 저장할지 선택하기 때문에 원하는대로 저장만 수행하기 위해서 결과가 true 인 값을 리턴하도록 하면 된다.
public class Entity implements Persistable<Long>{
@Id
private Long id;
@CreatedDate
@Column(name = "create_date", nullable = false)
private LocalDateTime createDate;
@Override
public Long getId() {
return id;
}
@Override
public boolean isNew() {
return createDate==null;
}
}
해결 방법으로 제시한 위의 코드는 일반적으로 엔티티에 생성 날짜나, 업데이트 날짜 등을 필드로 많이 사용한다. 그리고 해당 값들을 JPA auditing 기능이 persist 단계에서 자동으로 값을 넣어준다. 저 값을 isNew() 함수의 결과에 조건에 넣는다면 저 값은 persist 되기 전까진 항상 null 이기 때문에 새로운 객체로 분기를 타게되고, insert 만 수행되는 원하는 결과를 얻을 수 있다.
반응형