일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- db
- spring boot
- Firebase
- page
- Flutter
- Binding
- React JS
- 오류
- 플러터
- 깃허브
- 리엑트
- .NET
- Animation
- 함수
- 마우이
- 닷넷
- 애니메이션
- typescript
- 바인딩
- Maui
- AnimationController
- JavaScript
- listview
- MVVM
- 파이어베이스
- MS-SQL
- MSSQL
- GitHub
- HTML
- 자바스크립트
- Today
- Total
개발노트
10. [Spring Boot] Entity 관계 매핑하기(@ManyToOne, @OneToMnay) 본문
10. [Spring Boot] Entity 관계 매핑하기(@ManyToOne, @OneToMnay)
mroh1226 2024. 5. 13. 18:32Entity 관계설정과 JOIN 연결.
- Entity 관계는 데이터베이스의 테이블 간의 관계를 객체지향적으로 표현하고, JOIN은 이러한 관계를 이용하여 데이터를 효율적으로 조회하고 조합하는 기능을 제공합니다.
- JPA를 사용하여 Entity 관계를 정의하면 SQL을 직접 작성하지 않고도 객체 지향적으로 데이터를 다룰 수 있으며, 필요한 경우에는 JPA가 내부적으로 SQL을 생성하여 JOIN을 수행합니다.
- Entity 관계와 JOIN은 데이터베이스 모델링과 데이터 액세스 계층의 중요한 요소이며, 잘 정의된 관계와 효율적인 JOIN은 데이터베이스 성능과 코드 유지보수성에 긍정적인 영향을 미칩니다.
따라서, Entity 관계설정으로 JOIN의 형태로 데이터를 조회할 수 있습니다.
Entity 관계 예시.
cocktail과 mixtype은 mixtype_id를 통해, 아래와 같은 관계를 형성하고 있습니다.
(cocktail : mixtype = N:1)
따라서, 아래와 같은 관계가 됩니다.
cocktail → mixtype 은 Many To One
mixtype → cocktail 은 One To Many
mixtype_id에 포함된 cocktail 리스트를 조회하는 쿼리를 작성한다면, 아래와 같을 것입니다.
Select * From cocktail AS C
INNER JOIN mixtype AS M ON C.mixtype_id = M.mixtype_id
where M.mixtype_id = 1
이렇게 결과가 나올 것입니다.
Entity 관계 설정하기.
Entity 관계를 JPA에서 정의할 때는 @OneToMany, @ManyToOne, @OneToOne, @ManyToMany 등의 애노테이션을 사용합니다. 이러한 애노테이션을 통해 양방향 관계를 설정하고 엔티티 간의 매핑을 정의할 수 있습니다.
칵테일 Entity (Cocktail.java)
@Entity
@Getter
@Setter
@Table(name = "cocktail")
public class Cocktail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cocktail_id")
private Long cocktailId;
// @ManyToOne: 다대일(Many-to-One) 관계를 정의하는 애노테이션
// fetch = FetchType.LAZY: MixType 엔티티를 지연 로딩 방식으로 가져옵니다.
// @JoinColumn: 현재 엔티티의 외래 키(Foreign Key)를 지정합니다.
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore // 직렬화 및 역직렬화 시 무한 재귀를 방지하기 위한 애노테이션
@JoinColumn(name = "mixtype_id") // MixType 엔티티의 기본 키를 참조하는 외래 키 컬럼명을 지정합니다.
private MixType mixType;
@Column(name = "name")
private String name;
// 기타 다른 필드들...
}
믹스타입 Entity (MixType.java)
@Entity
@Getter
@Setter
@Table(name = "mixtype")
public class MixType {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "mixtype_id")
private Long mixtypeId;
// @OneToMany: 일대다(One-to-Many) 관계를 정의합니다.
// mappedBy = "mixType": Cocktail 엔티티에서 MixType 엔티티와의 관계를 소유하는 필드명을 지정합니다.
@OneToMany(mappedBy = "mixType")
@ToString.Exclude // ToString 메서드에서 해당 필드를 제외합니다 (무한 루프 방지)
private List<Cocktail> cocktails = new ArrayList<>();
@Column(name = "name", length = 255)
private String name;
}
- Cocktail 엔티티와 MixType 엔티티는 일대다 관계를 가지며, 한 개의 **Cocktail**은 하나의 **MixType**을 가리킵니다.
- MixType 엔티티는 Cocktail 엔티티와의 역방향 관계를 가지며, 하나의 **MixType**은 여러 개의 **Cocktail**을 가질 수 있습니다.
- 이러한 관계 설정을 통해 JPA는 엔티티 간의 관계를 효율적으로 매핑하고, 필요에 따라 데이터를 로딩하여 사용할 수 있습니다. 엔티티 간의 관계 설정은 데이터베이스 테이블 간의 JOIN 연산을 제어하고, 객체지향적인 설계를 구현하는 데 중요한 역할을 합니다.
- @JsonIgnore 사용하는 이유: https://mroh1226.tistory.com/209
FetchType
FetchType은 JPA(Java Persistence API)에서 엔티티 간의 연관 관계를 로드할 때 사용되는 옵션을 지정하는 열거형(Enum) 타입입니다. **FetchType**은 엔티티의 연관 관계를 어떻게 로딩할지 결정하며, 데이터베이스 쿼리 수행 시 관련된 엔티티를 함께 가져오거나 지연해서 가져올 수 있습니다.
FetchType 종류
- EAGER (즉시 로딩)
- **FetchType.EAGER**로 지정합니다.
- 연관된 엔티티를 부모 엔티티와 함께 즉시 로드합니다.
- 관련된 모든 데이터를 한 번에 로드하기 때문에 즉시 로딩은 간단하고 편리하지만, 데이터를 불필요하게 많이 가져올 수 있어 성능 문제가 발생할 수 있습니다.
- 일반적으로 관련 엔티티가 항상 함께 사용되는 경우에 사용합니다.
@ManyToOne(fetch = FetchType.EAGER)
- LAZY (지연 로딩)
- **FetchType.LAZY**로 지정합니다.
- 연관된 엔티티를 실제로 사용할 때까지 로드를 지연합니다.
- 필요한 시점에 데이터베이스에서 연관된 엔티티를 로드하여 성능을 최적화할 수 있습니다.
- 프록시(Proxy) 객체를 사용하여 지연 로딩을 구현합니다.
@ManyToOne(fetch = FetchType.LAZY)
FetchType 선택
- EAGER (즉시 로딩) vs. LAZY (지연 로딩)
- 즉시 로딩(EAGER): 연관된 엔티티를 즉시 로드하므로 데이터를 사용할 때 성능적인 이점은 있지만, 데이터 양이 많거나 성능에 영향을 줄 수 있습니다.
- 지연 로딩(LAZY): 연관된 엔티티를 실제로 사용할 때 로드하여 성능을 최적화할 수 있습니다. 필요한 시점에 데이터를 로드하기 때문에 불필요한 데이터베이스 호출을 줄일 수 있습니다.
- 기본값
- @ManyToOne 또는 **@OneToMany**에서 fetch 속성을 지정하지 않으면 기본적으로 LAZY 로딩이 적용됩니다.
- 하위 컬렉션(@OneToMany)을 즉시 로딩하려면 명시적으로 **fetch = FetchType.EAGER**를 설정해야 합니다.
칵테일 Repository (CocktailRepository.java)
@Repository
public interface CocktailRepository extends JpaRepository<Cocktail,Long> {
List<Cocktail> findByMixTypeMixtypeId(Long mixtypeId);
}
- 쿼리 메소드 작성법: https://mroh1226.tistory.com/210
칵테일 Service (CocktailService.java)
@Service
public class CocktailService {
@Autowired
public List<Cocktail> findByCocktailListMixTypeId(Long mixtypeId){
return cocktailRepository.findByMixTypeMixtypeId(mixtypeId);
}
}
위의 CocktailRepository 인터페이스는 **JpaRepository**를 상속받고 있습니다. 따라서 Spring Data JPA에서 제공하는 기본적인 CRUD(Create, Read, Update, Delete) 메서드뿐만 아니라 사용자 정의 쿼리 메서드를 정의할 수 있습니다.
findByMixTypeMixtypeId 메서드는 다음과 같이 해석됩니다:
- findBy: 데이터를 조회할 대상 필드를 지정합니다. 여기서는 MixType 엔티티를 참조하는 mixType 필드를 기준으로 조회할 것임을 나타냅니다.
- MixType: mixType 필드의 타입인 **MixType**을 나타냅니다.
- MixtypeId: MixType 엔티티의 mixtypeId 필드를 기준으로 조회할 것임을 나타냅니다. 이는 MixType 엔티티의 기본 키(primary key)를 의미합니다.
따라서 findByMixTypeMixtypeId 메서드는 Cocktail 엔티티를 조회할 때 해당 **Cocktail**의 mixType 필드가 주어진 mixtypeId 값과 일치하는 경우를 찾습니다. 즉, 특정 **mixtypeId**를 가진 **MixType**에 속한 모든 Cocktail 엔티티들을 반환합니다.
칵테일 Controller (CocktailController.java)
@RestController
@RequestMapping("/cocktails")
public class CocktailController {
@Autowired
private CocktailService cocktailService;
// HTTP GET 요청을 처리하는 핸들러 메서드
// URI: /cocktails/mixtypeId/{mixtype_id}
@GetMapping("/mixtypeId/{mixtype_id}")
public ResponseEntity<List<Cocktail>> getCocktailsMixtypeId(@PathVariable("mixtype_id") Long mixtypeId) {
// CocktailService를 사용하여 mixtypeId에 해당하는 Cocktail 엔티티들을 조회
List<Cocktail> cocktails = cocktailService.findByCocktailListMixTypeId(mixtypeId);
// 조회 결과에 따라 응답 처리
if (cocktails.isEmpty()) {
// 조회된 결과가 없는 경우: HTTP 상태 코드 204(No Content)를 반환
return ResponseEntity.noContent().build();
} else {
// 조회된 결과가 있는 경우: HTTP 상태 코드 200(OK)와 조회된 데이터를 반환
return ResponseEntity.ok(cocktails);
}
}
}
- @RestController: 이 클래스는 RESTful 웹 서비스의 컨트롤러임을 나타냅니다. 이 클래스에서 정의된 메서드들은 JSON 또는 XML 형식의 응답을 반환할 수 있습니다.
- @RequestMapping("/cocktails"): 이 컨트롤러의 모든 요청은 /cocktails 경로를 기본 경로로 가집니다.
- @Autowired private CocktailService cocktailService;: CocktailService 인스턴스를 자동으로 주입받습니다. 이를 통해 서비스 계층의 메서드를 호출하여 비즈니스 로직을 수행할 수 있습니다.
- @GetMapping("/mixtypeId/{mixtype_id}"): HTTP GET 요청을 처리하는 핸들러 메서드를 정의합니다. 요청 경로는 **/cocktails/mixtypeId/{mixtype_id}**로 지정됩니다. **{mixtype_id}**는 경로 변수로 사용되며, 해당 값을 mixtypeId 파라미터로 전달받습니다.
- @PathVariable("mixtype_id") Long mixtypeId: 경로 변수 **{mixtype_id}**의 값이 mixtypeId 파라미터로 매핑됩니다.
- cocktailService.findByCocktailListMixTypeId(mixtypeId): **CocktailService**의 findByCocktailListMixTypeId 메서드를 호출하여 주어진 **mixtypeId**에 해당하는 Cocktail 엔티티들을 조회합니다.
- ResponseEntity: HTTP 응답을 생성하기 위한 Spring의 클래스입니다. **List<Cocktail>**을 포함한 응답을 생성할 수 있습니다.
- ResponseEntity.noContent().build(): 조회된 데이터가 없는 경우, HTTP 상태 코드 204(No Content)를 반환합니다.
- ResponseEntity.ok(cocktails): 조회된 데이터가 있는 경우, HTTP 상태 코드 200(OK)와 조회된 cocktails 데이터를 반환합니다.
이렇게 구현된 컨트롤러는 클라이언트의 요청에 따라 **mixtypeId**에 해당하는 Cocktail 엔티티들을 조회하여 JSON 형식으로 반환합니다. 조회된 데이터가 없을 경우 204(No Content) 상태 코드를 반환하고, 조회된 데이터가 있을 경우 200(OK) 상태 코드와 데이터를 반환합니다. 이를 통해 클라이언트는 필요한 데이터를 요청하고 응답으로 받을 수 있습니다.
GET 호출
'서버 개발 > Spring Boot' 카테고리의 다른 글
12. [Spring Boot] 이유 없이 갑자기 디펜던시(Dependency) 적용이 안된다면? (0) | 2024.06.24 |
---|---|
11. [Spring Boot] DTO 사용하기 (JSON 데이터 커스텀하기) (0) | 2024.05.14 |
9. [Spring Boot] 쿼리 메소드 (Repository 안의 메소드명에 따라 쿼리가 달라진다.) (0) | 2024.05.09 |
8. [Spring Boot] @ManyToOne 무한재귀 호출 문제 해결하기 (0) | 2024.04.30 |
7. [Spring Boot] PropertyReferenceException 에러 해결 (Java "_" 언더바 인식 못함 문제) (0) | 2024.04.30 |