Spring Boot + JPA: 복합 기본키(@EmbeddedId) 중 특정 컬럼으로 조회하기
Spring Boot와 JPA를 활용하면서 복합 기본키(Composite Primary Key)를 사용하는 경우가 있습니다. 특히 @EmbeddedId
를 사용하는 상황에서, 복합 기본키 중 특정 컬럼만 조건으로 조회하고 싶을 때 구현 방법을 알아보겠습니다. 이 글은 해당 문제를 해결하기 위해 필요한 모든 과정을 자세히 다룹니다.
1. 복합 기본키와 @EmbeddedId
복합 기본키는 테이블의 기본키가 두 개 이상의 컬럼으로 이루어진 경우를 말합니다. JPA에서는 복합 기본키를 @EmbeddedId
또는 @IdClass
를 이용해 매핑할 수 있습니다. 이 글에서는 @EmbeddedId
를 사용하는 방법을 기준으로 설명합니다.
복합 키 클래스 정의
먼저, 복합 기본키를 나타내는 클래스를 정의해야 합니다. 이 클래스는 반드시 @Embeddable
어노테이션으로 선언해야 하며, Serializable
인터페이스를 구현해야 합니다.
import jakarta.persistence.Embeddable;
import java.io.Serializable;
import java.util.Objects;
@Embeddable
public class CompositeKey implements Serializable {
private String convsId;
private String anotherId;
// 기본 생성자
public CompositeKey() {}
// 생성자
public CompositeKey(String convsId, String anotherId) {
this.convsId = convsId;
this.anotherId = anotherId;
}
// Getter/Setter
public String getConvsId() {
return convsId;
}
public void setConvsId(String convsId) {
this.convsId = convsId;
}
public String getAnotherId() {
return anotherId;
}
public void setAnotherId(String anotherId) {
this.anotherId = anotherId;
}
// equals & hashCode 재정의
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CompositeKey that = (CompositeKey) o;
return Objects.equals(convsId, that.convsId) && Objects.equals(anotherId, that.anotherId);
}
@Override
public int hashCode() {
return Objects.hash(convsId, anotherId);
}
}
엔티티 클래스 정의
복합 키를 사용하는 엔티티 클래스는 @EmbeddedId
를 사용해 복합 키를 참조합니다.
import jakarta.persistence.*;
@Entity
public class MyEntity {
@EmbeddedId
private CompositeKey id;
private String someData;
// 기본 생성자
public MyEntity() {}
// 생성자
public MyEntity(CompositeKey id, String someData) {
this.id = id;
this.someData = someData;
}
// Getter/Setter
public CompositeKey getId() {
return id;
}
public void setId(CompositeKey id) {
this.id = id;
}
public String getSomeData() {
return someData;
}
public void setSomeData(String someData) {
this.someData = someData;
}
}
2. 복합 키 컬럼 중 특정 컬럼으로 조회하기
@EmbeddedId
를 사용하는 경우, 복합 키의 특정 컬럼만을 조건으로 조회하려면 다음과 같은 방법을 사용할 수 있습니다.
방법 1: JPQL 사용
JPQL에서 복합 키의 특정 필드에 접근하려면 경로 탐색을 활용해야 합니다.
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface MyEntityRepository extends CrudRepository<MyEntity, CompositeKey> {
@Query("SELECT e FROM MyEntity e WHERE e.id.convsId = :convsId")
List<MyEntity> findByConvsId(String convsId);
}
사용 예
@Autowired
private MyEntityRepository myEntityRepository;
public void testQuery() {
String convsId = "12345";
List<MyEntity> results = myEntityRepository.findByConvsId(convsId);
results.forEach(System.out::println);
}
방법 2: Criteria API 사용
Criteria API를 사용하면 동적으로 쿼리를 생성할 수 있습니다.
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.criteria.*;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class MyEntityCriteriaRepository {
@PersistenceContext
private EntityManager entityManager;
public List<MyEntity> findByConvsId(String convsId) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = cb.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
// 복합 키의 convsId 조건 설정
Predicate condition = cb.equal(root.get("id").get("convsId"), convsId);
query.where(condition);
return entityManager.createQuery(query).getResultList();
}
}
사용 예
@Autowired
private MyEntityCriteriaRepository criteriaRepository;
public void testCriteria() {
String convsId = "12345";
List<MyEntity> results = criteriaRepository.findByConvsId(convsId);
results.forEach(System.out::println);
}
방법 3: Example 사용
Spring Data JPA의 Example
객체를 사용하면 간단한 조회 조건을 설정할 수 있습니다.
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.repository.CrudRepository;
public interface MyEntityRepository extends CrudRepository<MyEntity, CompositeKey> {
List<MyEntity> findAll(Example<MyEntity> example);
}
사용 예
@Autowired
private MyEntityRepository myEntityRepository;
public void testExample() {
CompositeKey key = new CompositeKey();
key.setConvsId("12345");
MyEntity probe = new MyEntity();
probe.setId(key);
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("id.convsId", ExampleMatcher.GenericPropertyMatchers.exact());
Example<MyEntity> example = Example.of(probe, matcher);
List<MyEntity> results = myEntityRepository.findAll(example);
results.forEach(System.out::println);
}
3. 어떤 방법을 선택할까?
- 간단한 조회: 특정 조건만으로 조회하려면 JPQL을 사용하는 것이 가장 간단합니다.
- 동적 조건 추가: 여러 조건을 조합하거나 동적으로 조건을 설정하려면 Criteria API를 사용하는 것이 유리합니다.
- 간단한 예제 기반 조회: 조건이 간단하고 데이터가 샘플 형태로 준비되어 있다면
Example
을 사용하는 것도 좋은 선택입니다.
요약
@EmbeddedId
를 사용하는 경우, 복합 기본키 중 특정 필드 조건만으로 조회하려면 JPQL, Criteria API, 또는 Example 객체를 활용할 수 있습니다.- 사용 사례에 따라 적합한 방법을 선택하세요.
이 글이 복합 키를 사용하는 JPA 프로젝트를 개발할 때 도움이 되길 바랍니다. 추가적인 질문이 있다면 댓글로 남겨주세요!
Comments
Post a Comment