본문으로 건너뛰기
ElastiCORE 3.0 은 릴리스 후보(RC)입니다: Maven Central 의 3.0.261022-rc1. 2.2 라인 프로젝트는 2.2 문서를 보세요.
버전: 3.0

관계와 값 객체

참조​

타입이 엔티티인 필드는 참조이고, 기본으로 @ManyToOne 이 붙습니다.

fields:
parent: ParentEntity # @ManyToOne (기본)
children: List<Child> @OneToMany(mappedBy="parent")
profile: Profile @OneToOne
tags: List<Tag> @ManyToMany
comment: Comment @column(parent_comment_id) # @JoinColumn(name="parent_comment_id")

요청이 보내는 것: 키 필드​

@expose / @service 엔티티의 DTO 는 to-one 참조를 두 필드로 그립니다: 응답용 중첩 DTO(OpenAPI 에서 READ_ONLY)와 저장용 키 필드. 키 필드의 이름은 필드 이름 + 대상의 키입니다(batch 의 키가 batchId 면 batchBatchId, 키 이름이 id 면 batchId). DDD 번들에서 다른 루트를 가리키는 참조는 대상 키 이름이 참조 이름으로 시작하면 그 이름(member -> memberId, item -> itemCode), 아니면 참조 + 키(book, 키 isbn -> bookIsbn)입니다. 같은 이름의 필드가 이미 있으면 DSL 경고 후 객체 참조로 남습니다.

필수 참조: post: Post!​

! 는 컬럼을 NOT NULL 로 만들고, v3·Kotlin·TypeScript 출력에서는(3.0.261022-rc1 부터) 키 필드가 필수, 중첩 DTO 는 선택입니다:

Comment:
meta: entity @root @expose(20) -- comment
fields:
commentId: long @id @sequence
post: Post! -- parent post
CommentDTO (v3, 생성)
@Schema(description = "parent post" , accessMode = Schema.AccessMode.READ_ONLY )
private PostDTO post; // 응답용 - 요청에서는 선택

@Schema(description = "postPostId" , requiredMode=Schema.RequiredMode.REQUIRED )
@NotNull
private Long postPostId; // 저장 요청에 필수
CommentDTO.ts
post?: PostDTO;
postPostId: number;

저장 요청은 {"postPostId": 1, ...} 를 보내고, 없으면 400 입니다. 2.x 생성기와 jpa-springboot 출력은 예전 그대로입니다 (중첩 post 에 @NotNull 이 붙어 요청은 둘 다 보내야 함). dto.yml 에 직접 선언한 DTO 는 필드에 ! 를 씁니다: postId: long! @ref(post.postId).

없는 행을 가리키는 참조: 404​

DDD 번들에서 없는 행을 가리키는 키("productId": 99)는 저장 전에 확인되어(requireReferences) 404 Product 99 does not exist(코드 reference.OrderLine.product)입니다 - 직접 조회해서 확인하지 마세요.

애그리거트 사이의 참조 (DDD 번들)​

다른 루트를 가리키는 to-one 참조는 ID 필드와 같은 컬럼의 읽기 전용 조인이 되고, 애그리거트는 다른 루트를 통해 쓸 수 없습니다. DDD 참고. 객체 참조로 두려면 @objectref. 참조에 @updatable(false) 를 붙이면 수정해도 저장된 ID 가 남습니다 - 리뷰는 처음 정한 상품에 남습니다.

@ref - 참조 너머의 값​

dto:
OrderLineDTO:
meta: dto @template(OrderLine)
fields:
itemName: string @ref(item.name) # 응답에 품목 이름

v3 번들에서 누가 쓸 수 있는지 정한 엔티티(@access, @owner, @password, 필드의 @access(admin))로 가는 @ref 는 읽기 전용이고, @password 를 읽는 @ref 는 DSL 경고와 함께 빠집니다. 참조의 키를 가리키는 @ref(assignee.memberId) 는 전처럼 참조가 가리키는 행을 바꿉니다.

@fk - 관계 없이 외래 키 정보만​

code: string @fk(Target) (또는 @fk(Target.field), 복합 키는 @fk(Target.field, group))은 @ManyToOne 없이 평범한 컬럼에 외래 키 정보를 남깁니다 - 레거시 DB, 지연 로딩을 피하고 싶을 때.

값 객체: @embeddable​

entity:
Address:
meta: entity @embeddable -- 주소
fields:
street1: string(50)!
city: string(50)!
zipcode: string(10)!
countryCode: string(2)!

CreditCard:
meta: entity @embeddable -- 결제 카드
fields:
creditCardNumber: string(30)! @writeonly # accepted, never sent back
creditCardType: CreditCardType!
creditCardExpDate: string(5)! # MM/YY

Customer:
fields:
homeAddress: Address! @Embedded # 필수 값
PurchaseOrder:
fields:
deliveryAddress: Address @Embedded # 선택 값
creditCard: CreditCard! @Embedded
  • 값 객체의 컬럼은 그것을 담는 엔티티의 테이블에 생깁니다.
  • v3 번들에서 DTO 는 값 객체를 중첩 객체로 그대로 싣고, 값 객체의 필드에 DTO 의 검증·JSON 규칙(@NotNull, @Size, @writeonly 의 @JsonProperty(access = WRITE_ONLY))이 붙으며 DTO 쪽 필드에는 @Valid 가 붙습니다.
  • DDD 번들에서 값 객체는 불변입니다: setter 가 없고, 필드마다 바뀐 복사본을 주는 withXxx() 가 있습니다 (address.withCity("Rotterdam")).
  • 선택으로 담은 값(deliveryAddress: Address @Embedded, ! 없음): 3.0.261022-rc1 부터 값 객체의 ! 필드가 그 테이블에 NOT NULL 컬럼을 만들지 않습니다. 값이 오면 필수 필드를 검사하고(400), 값이 없는 행은 그대로 저장됩니다. 전에는 배송지를 보내지 않은 주문이 NULL not allowed for column "ZIPCODE" 로 저장되지 않았습니다.
  • 값 객체는 통째로 교체됩니다. @writeonly 필드가 있는 값 객체를 읽어서 그대로 저장하면 그 필드는 비어서 옵니다 - @writeonly 는 생성할 때만 받는 값에 씁니다.
  • 식별자 타입 래핑(OrderId 같은 키 클래스)은 지원하지 않습니다.