Spring Data JPA에서 새로운 Entity인지 판단하는 것이 중요한 이유
Spring Data JPA에서 엔티티가 새로운 엔티티인지 판단하는 방법은 식별자(ID)의 값을 기준으로 이루어집니다.
기본적으로 JPA는 엔티티가 새로운 상태인지 또는 이미 존재하는 상태인지를 다음과 같은 조건을 통해 판단합니다.
null
인지 확인JPA에서는 식별자(ID) 필드가 null
이면 해당 엔티티를 새로운 엔티티로 간주합니다.
즉, @Id
로 지정된 필드에 값이 없으면 JPA는 아직 이 엔티티가 데이터베이스에 저장되지 않았다고 판단합니다.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
null
인 경우:User user = new User();
user.setName("Alice");
// id가 null이므로 새로운 엔티티로 간주됨
User user = new User();
user.setId(1L); // id가 null이 아니므로 기존 엔티티로 간주됨
user.setName("Bob");
EntityManager
의 persist()
동작 원리EntityManager
의 persist()
메서드는 엔티티가 새로운 상태일 때만 동작합니다.
새로운 엔티티로 간주되면 영속성 컨텍스트에 등록되고, 이후 flush()
시점에 데이터베이스에 저장됩니다.
EntityManager em = ...;
User user = new User();
user.setName("Alice");
em.persist(user); // user는 새로운 엔티티로 간주됨
save()
메서드Spring Data JPA의 save()
메서드는 내부적으로 새로운 엔티티인지 판단하여 다음과 같이 동작합니다:
persist()
호출.merge()
호출.null
이면 새로운 엔티티로 판단.null
이 아니고, 데이터베이스에 존재하면 기존 엔티티로 판단.User newUser = new User();
newUser.setName("Alice");
// 새로운 엔티티로 판단하여 persist() 호출
userRepository.save(newUser);
User existingUser = userRepository.findById(1L).orElseThrow();
existingUser.setName("Updated Name");
// 기존 엔티티로 판단하여 merge() 호출
userRepository.save(existingUser);
save()
메서드를 사용하지 않고 직접 새로운 엔티티인지 확인하려면 다음 방법을 사용할 수 있습니다.
if (user.getId() == null) {
System.out.println("새로운 엔티티입니다.");
} else {
System.out.println("기존 엔티티입니다.");
}
Persistable
인터페이스를 구현하여 새로운 엔티티인지 판단하는 로직을 커스터마이징할 수 있습니다.
import org.springframework.data.domain.Persistable;
@Entity
public class User implements Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Override
public Long getId() {
return id;
}
@Override
public boolean isNew() {
// 새로운 엔티티 기준 정의 (예: id가 null이면 새로운 엔티티)
return this.id == null;
}
}
식별자 생성 전략
@GeneratedValue
)되지 않고 애플리케이션에서 직접 할당할 경우, 새로운 엔티티 판단이 다르게 작동할 수 있습니다.save()
호출 시 충돌이 발생할 수 있습니다.준영속 상태 확인
merge()
가 호출됩니다.null
인 경우 새로운 엔티티로 판단합니다.save()
는 이를 바탕으로 persist()
또는 merge()
를 호출합니다.Persistable
인터페이스를 활용할 수 있습니다.추가 학습 자료