반응형
model(BaseEntity, Product, ProductDto, ProductItem, ProductItemDto)
BaseEntity
package com.zerobase.cms.order.domain.model;
import java.time.LocalDateTime;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@Getter
@MappedSuperclass
@EntityListeners(value = {AuditingEntityListener.class})
public class BaseEntity {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
}
기본 엔티티 (BaseEntity)
이 코드는 데이터베이스 엔티티의 공통 속성을 정의하는 추상 클래스(BaseEntity)입니다. 엔티티는 데이터베이스 테이블에 매핑되는 Java 객체이며, 각 속성은 테이블의 컬럼에 해당합니다. BaseEntity는 모든 엔티티가 공통적으로 가져야 하는 생성 시간(createdAt)과 수정 시간(modifiedAt) 속성을 정의하고, JPA Auditing 기능을 사용하여 이러한 속성을 자동으로 관리합니다.
1. 클래스 구조 및 어노테이션
- import java.time.LocalDateTime;: LocalDateTime 클래스를 가져옵니다. 이 클래스는 날짜와 시간을 함께 나타냅니다.
- import javax.persistence.EntityListeners;: EntityListeners 어노테이션을 가져옵니다. 이 어노테이션은 엔티티의 생명주기 이벤트 (생성, 수정, 삭제 등)를 감지하는 리스너를 지정합니다.
- import javax.persistence.MappedSuperclass;: MappedSuperclass 어노테이션을 가져옵니다. 이 어노테이션은 해당 클래스가 엔티티가 아니라 다른 엔티티의 속성을 상속하기 위한 클래스임을 나타냅니다.
- import lombok.Getter;: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 getter 메서드를 자동으로 생성해줍니다.
- import org.springframework.data.annotation.CreatedDate;: CreatedDate 어노테이션을 가져옵니다. 이 어노테이션은 엔티티가 생성될 때 자동으로 설정되는 속성을 지정합니다.
- import org.springframework.data.annotation.LastModifiedDate;: LastModifiedDate 어노테이션을 가져옵니다. 이 어노테이션은 엔티티가 수정될 때 자동으로 설정되는 속성을 지정합니다.
- import org.springframework.data.jpa.domain.support.AuditingEntityListener;: AuditingEntityListener 클래스를 가져옵니다. 이 클래스는 JPA Auditing 기능을 사용하여 엔티티의 생성 및 수정 시간을 자동으로 관리합니다.
- @Getter: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 getter 메서드를 자동으로 생성해줍니다. getter 메서드는 객체의 필드 값을 외부에서 읽을 수 있도록 해줍니다.
- @MappedSuperclass: 이 어노테이션은 해당 클래스가 엔티티가 아니라 다른 엔티티의 속성을 상속하기 위한 클래스임을 나타냅니다. BaseEntity를 상속하는 엔티티는 createdAt 및 modifiedAt 속성을 자동으로 갖게 됩니다.
- @EntityListeners(value = {AuditingEntityListener.class}): 이 어노테이션은 엔티티의 생명주기 이벤트를 감지하는 리스너를 지정합니다. 여기서는 AuditingEntityListener를 지정하여 JPA Auditing 기능을 활성화합니다. AuditingEntityListener는 엔티티가 생성되거나 수정될 때 CreatedDate 및 LastModifiedDate 어노테이션이 붙은 속성을 자동으로 설정합니다.
- public class BaseEntity { ... }: BaseEntity 클래스를 정의합니다. public은 이 클래스가 모든 패키지에서 접근 가능하다는 것을 의미합니다.
2. 클래스 필드
- @CreatedDate private LocalDateTime createdAt;: 엔티티가 생성된 시간을 나타내는 속성입니다.
- @CreatedDate: 이 어노테이션은 엔티티가 생성될 때 자동으로 설정되는 속성을 지정합니다. AuditingEntityListener가 이 어노테이션을 감지하여 엔티티가 생성될 때 현재 시간으로 설정합니다.
- private LocalDateTime createdAt;: LocalDateTime 타입의 createdAt 필드를 정의합니다. LocalDateTime은 날짜와 시간을 함께 나타내는 클래스입니다. private은 이 필드가 BaseEntity 클래스 내에서만 접근 가능하다는 것을 의미합니다.
- @LastModifiedDate private LocalDateTime modifiedAt;: 엔티티가 마지막으로 수정된 시간을 나타내는 속성입니다.
- @LastModifiedDate: 이 어노테이션은 엔티티가 수정될 때 자동으로 설정되는 속성을 지정합니다. AuditingEntityListener가 이 어노테이션을 감지하여 엔티티가 수정될 때 현재 시간으로 설정합니다.
- private LocalDateTime modifiedAt;: LocalDateTime 타입의 modifiedAt 필드를 정의합니다. private은 이 필드가 BaseEntity 클래스 내에서만 접근 가능하다는 것을 의미합니다.
3. 핵심 개념 및 추가 설명
- JPA (Java Persistence API): JPA는 Java에서 데이터베이스와 상호 작용하기 위한 표준 인터페이스입니다. JPA를 사용하면 객체 지향적인 방식으로 데이터베이스를 다룰 수 있으며, 데이터베이스 종류에 상관없이 동일한 코드를 사용할 수 있습니다.
- 엔티티 (Entity): 엔티티는 데이터베이스 테이블에 매핑되는 Java 객체입니다. 각 엔티티는 테이블의 로우에 해당하며, 엔티티의 속성은 테이블의 컬럼에 해당합니다.
- JPA Auditing: JPA Auditing은 엔티티의 생성 및 수정 시간을 자동으로 관리하는 기능입니다. JPA Auditing을 사용하면 엔티티에 생성 시간과 수정 시간을 저장하는 코드를 직접 작성할 필요가 없습니다.
- @MappedSuperclass: 이 어노테이션은 해당 클래스가 엔티티가 아니라 다른 엔티티의 속성을 상속하기 위한 클래스임을 나타냅니다. MappedSuperclass 어노테이션이 붙은 클래스는 데이터베이스 테이블에 매핑되지 않으며, 다른 엔티티가 상속하여 사용할 수 있는 공통 속성을 정의합니다.
- 상속 (Inheritance): 상속은 객체 지향 프로그래밍의 핵심 개념 중 하나로, 기존 클래스의 속성과 메서드를 새로운 클래스에서 재사용할 수 있도록 해줍니다. 상속을 사용하면 코드 중복을 줄이고, 코드 재사용성을 높일 수 있습니다.
- Lombok: Lombok은 반복적인 코드를 줄여주는 Java 라이브러리입니다. @Getter, @Setter, @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor 등의 어노테이션을 사용하여 boilerplate 코드를 자동으로 생성할 수 있습니다.
Product
package com.zerobase.cms.order.domain.model;
import com.zerobase.cms.order.domain.product.AddProductForm;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.envers.AuditOverride;
import org.hibernate.envers.Audited;
@Entity
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Audited
@AuditOverride(forClass = BaseEntity.class)
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long sellerId;
private String name;
private String description;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "product_id")
private List<ProductItem> productItems = new ArrayList<>();
public static Product of(Long sellerId, AddProductForm form) {
return Product.builder()
.sellerId(sellerId)
.name(form.getName())
.description(form.getDescription())
.productItems(form.getItems().stream()
.map(piForm -> ProductItem.of(sellerId, piForm))
.collect(Collectors.toList()))
.build();
}
}
상품 엔티티 (Product)
이 코드는 상품 정보를 나타내는 엔티티 클래스(Product)입니다. 엔티티는 데이터베이스 테이블에 매핑되는 Java 객체이며, 각 속성은 테이블의 컬럼에 해당합니다. Product 엔티티는 상품 ID, 판매자 ID, 상품 이름, 상품 설명, 상품 아이템 목록 등의 정보를 저장합니다.
1. 클래스 구조 및 어노테이션
- import com.zerobase.cms.order.domain.product.AddProductForm;: AddProductForm 클래스를 가져옵니다. 이 클래스는 상품 추가 폼 데이터를 담는 객체입니다.
- import javax.persistence.CascadeType;: CascadeType 열거형을 가져옵니다. CascadeType은 엔티티 간의 연관 관계에서 발생하는 작업이 다른 엔티티에 미치는 영향을 정의합니다.
- import javax.persistence.Entity;: Entity 어노테이션을 가져옵니다. 이 어노테이션은 해당 클래스가 JPA 엔티티임을 나타냅니다.
- import javax.persistence.GeneratedValue;: GeneratedValue 어노테이션을 가져옵니다. 이 어노테이션은 기본 키 생성 전략을 지정합니다.
- import javax.persistence.GenerationType;: GenerationType 열거형을 가져옵니다. GenerationType은 기본 키 생성 전략의 타입을 정의합니다.
- import javax.persistence.Id;: Id 어노테이션을 가져옵니다. 이 어노테이션은 해당 필드가 엔티티의 기본 키임을 나타냅니다.
- import javax.persistence.JoinColumn;: JoinColumn 어노테이션을 가져옵니다. 이 어노테이션은 외래 키 컬럼을 지정합니다.
- import javax.persistence.OneToMany;: OneToMany 어노테이션을 가져옵니다. 이 어노테이션은 엔티티 간의 일대다 연관 관계를 지정합니다.
- import java.util.ArrayList;: ArrayList 클래스를 가져옵니다. ArrayList는 동적으로 크기가 조정되는 배열을 구현한 클래스입니다.
- import java.util.List;: List 인터페이스를 가져옵니다. List는 순서가 있는 데이터 컬렉션을 나타냅니다.
- import java.util.stream.Collectors;: Collectors 클래스를 가져옵니다. Collectors는 스트림 데이터를 수집하는 데 사용됩니다.
- import lombok.AllArgsConstructor;: Lombok 라이브러리의 어노테이션으로, 모든 필드를 인수로 받는 생성자를 자동으로 생성해줍니다.
- import lombok.Builder;: Lombok 라이브러리의 어노테이션으로, 빌더 패턴을 자동으로 생성해줍니다.
- import lombok.Getter;: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 getter 메서드를 자동으로 생성해줍니다.
- import lombok.NoArgsConstructor;: Lombok 라이브러리의 어노테이션으로, 인수가 없는 기본 생성자를 자동으로 생성해줍니다.
- import lombok.Setter;: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 setter 메서드를 자동으로 생성해줍니다.
- import org.hibernate.envers.AuditOverride;: AuditOverride 어노테이션을 가져옵니다. 이 어노테이션은 특정 클래스에 대한 감사 정보를 재정의합니다.
- import org.hibernate.envers.Audited;: Audited 어노테이션을 가져옵니다. 이 어노테이션은 해당 엔티티에 대한 감사 기능을 활성화합니다.
- @Entity: 이 어노테이션은 해당 클래스가 JPA 엔티티임을 나타냅니다. JPA는 Java Persistence API의 약자로, Java 객체를 데이터베이스 테이블에 매핑하는 기술입니다.
- @Setter: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 setter 메서드를 자동으로 생성해줍니다. setter 메서드는 객체의 필드 값을 외부에서 설정할 수 있도록 해줍니다.
- @Getter: Lombok 라이브러리의 어노테이션으로, 모든 필드에 대한 getter 메서드를 자동으로 생성해줍니다. getter 메서드는 객체의 필드 값을 외부에서 읽을 수 있도록 해줍니다.
- @Builder: Lombok 라이브러리의 어노테이션으로, 빌더 패턴을 자동으로 생성해줍니다. 빌더 패턴은 객체 생성을 더 유연하고 가독성 좋게 만들어줍니다.
- @NoArgsConstructor: Lombok 라이브러리의 어노테이션으로, 인수가 없는 기본 생성자를 자동으로 생성해줍니다. JPA는 엔티티에 기본 생성자가 필요합니다.
- @AllArgsConstructor: Lombok 라이브러리의 어노테이션으로, 모든 필드를 인수로 받는 생성자를 자동으로 생성해줍니다.
- @Audited: Hibernate Envers 라이브러리의 어노테이션으로, 해당 엔티티에 대한 감사 기능을 활성화합니다. 감사 기능은 엔티티의 변경 이력을 추적하고 관리하는 데 사용됩니다.
- @AuditOverride(forClass = BaseEntity.class): Hibernate Envers 라이브러리의 어노테이션으로, BaseEntity 클래스에 대한 감사 정보를 재정의합니다. 이 어노테이션을 사용하면 BaseEntity 클래스의 속성 (createdAt, modifiedAt 등)에 대한 감사 정보를 별도로 설정할 수 있습니다.
- public class Product extends BaseEntity { ... }: Product 클래스를 정의합니다. public은 이 클래스가 모든 패키지에서 접근 가능하다는 것을 의미합니다. extends BaseEntity는 Product 클래스가 BaseEntity 클래스를 상속받음을 나타냅니다. 상속을 통해 Product 클래스는 BaseEntity 클래스의 속성 (createdAt, modifiedAt 등)을 자동으로 갖게 됩니다.
2. 클래스 필드
- @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;: 상품 ID를 나타내는 속성입니다.
- @Id: 이 어노테이션은 해당 필드가 엔티티의 기본 키임을 나타냅니다. 기본 키는 테이블에서 각 로우를 고유하게 식별하는 데 사용되는 컬럼입니다.
- @GeneratedValue(strategy = GenerationType.IDENTITY): 이 어노테이션은 기본 키 생성 전략을 지정합니다. GenerationType.IDENTITY는 데이터베이스의 자동 증가 기능을 사용하여 기본 키를 생성함을 나타냅니다.
- private Long id;: Long 타입의 id 필드를 정의합니다. Long은 long 타입의 래퍼 클래스이며, null 값을 가질 수 있습니다. private은 이 필드가 Product 클래스 내에서만 접근 가능하다는 것을 의미합니다.
- private Long sellerId;: 판매자 ID를 나타내는 속성입니다.
- private String name;: 상품 이름을 나타내는 속성입니다.
- private String description;: 상품 설명을 나타내는 속성입니다.
- @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "product_id") private List<ProductItem> productItems = new ArrayList<>();: 상품 아이템 목록을 나타내는 속성입니다.
- @OneToMany(cascade = CascadeType.ALL): 이 어노테이션은 엔티티 간의 일대다 연관 관계를 지정합니다. Product 엔티티 하나는 여러 개의 ProductItem 엔티티를 가질 수 있습니다. cascade = CascadeType.ALL은 Product 엔티티에 대한 모든 작업 (생성, 수정, 삭제 등)이 연관된 ProductItem 엔티티에도 적용됨을 나타냅니다.
- @JoinColumn(name = "product_id"): 이 어노테이션은 외래 키 컬럼을 지정합니다. name = "product_id"는 ProductItem 테이블의 product_id 컬럼이 Product 테이블의 id 컬럼을 참조하는 외래 키임을 나타냅니다.
- private List<ProductItem> productItems = new ArrayList<>();: ProductItem 타입의 productItems 필드를 정의합니다. List는 순서가 있는 데이터 컬렉션을 나타내는 인터페이스이며, ArrayList는 List 인터페이스를 구현한 클래스입니다. new ArrayList<>()는 ProductItem 객체를 저장할 수 있는 빈 리스트를 생성합니다.
3. 메서드
3.1. of(Long sellerId, AddProductForm form)
- 기능: AddProductForm 객체를 사용하여 Product 객체를 생성합니다.}`
- public static Product of(Long sellerId, AddProductForm form): of 메서드를 정의합니다.
- public은 이 메서드가 모든 클래스에서 접근 가능하다는 것을 의미합니다.
- static은 이 메서드가 클래스 레벨 메서드임을 나타냅니다. 즉, 객체 생성 없이 클래스 이름으로 호출할 수 있습니다.
- Product는 반환 타입으로, 이 메서드가 Product 클래스의 인스턴스를 반환함을 나타냅니다.
- Long sellerId는 판매자 ID를 나타내는 파라미터입니다.
- AddProductForm form은 상품 추가 폼 데이터를 담는 객체를 나타내는 파라미터입니다.
- return Product.builder() ... .build();: 빌더 패턴을 사용하여 Product 객체를 생성하고 반환합니다.
- Product.builder(): Product 클래스의 빌더를 생성합니다.
- .sellerId(sellerId): 빌더에 판매자 ID를 설정합니다.
- .name(form.getName()): 빌더에 상품 이름을 설정합니다. form.getName()은 AddProductForm 객체에서 상품 이름을 가져오는 메서드입니다.
- .description(form.getDescription()): 빌더에 상품 설명을 설정합니다. form.getDescription()은 AddProductForm 객체에서 상품 설명을 가져오는 메서드입니다.
- .productItems(form.getItems().stream() ... .collect(Collectors.toList())): 빌더에 상품 아이템 목록을 설정합니다.
- form.getItems().stream(): AddProductForm 객체에서 상품 아이템 목록을 가져와 스트림으로 변환합니다.
- .map(piForm -> ProductItem.of(sellerId, piForm)): 스트림의 각 요소를 ProductItem 객체로 변환합니다. ProductItem.of(sellerId, piForm)은 ProductItem 클래스의 of 메서드를 호출하여 ProductItem 객체를 생성하는 람다 표현식입니다.
- .collect(Collectors.toList()): 스트림의 요소들을 List로 수집합니다.
- .build(): 빌더에 설정된 속성들을 사용하여 Product 객체를 생성합니다.
- public static Product of(Long sellerId, AddProductForm form): of 메서드를 정의합니다.
4. 핵심 개념 및 추가 설명
- JPA (Java Persistence API): JPA는 Java에서 데이터베이스와 상호 작용하기 위한 표준 인터페이스입니다. JPA를 사용하면 객체 지향적인 방식으로 데이터베이스를 다룰 수 있으며, 데이터베이스 종류에 상관없이 동일한 코드를 사용할 수 있습니다.
- 엔티티 (Entity): 엔티티는 데이터베이스 테이블에 매핑되는 Java 객체입니다. 각 엔티티는 테이블의 로우에 해당하며, 엔티티의 속성은 테이블의 컬럼에 해당합니다.
- 기본 키 (Primary Key): 기본 키는 테이블에서 각 로우를 고유하게 식별하는 데 사용되는 컬럼입니다.
- 외래 키 (Foreign Key): 외래 키는 다른 테이블의 로우를 참조하는 데 사용되는 컬럼입니다. 외래 키는 테이블 간의 관계를 설정하는 데 사용됩니다.
- JPA 연관 관계 (JPA Relationship): JPA 연관 관계는 엔티티 간의 관계를 나타냅니다. 주요 연관 관계는 다음과 같습니다.
- 일대일 (OneToOne): 한 엔티티가 다른 엔티티 하나와만 연관됩니다.
- 일대다 (OneToMany): 한 엔티티가 다른 엔티티 여러 개와 연관됩니다.
- 다대일 (ManyToOne): 여러 엔티티가 다른 엔티티 하나와 연관됩니다.
- 다대다 (ManyToMany): 여러 엔티티가 다른 엔티티 여러 개와 연관됩니다.
- CascadeType: CascadeType은 엔티티 간의 연관 관계에서 발생하는 작업이 다른 엔티티에 미치는 영향을 정의합니다. 주요 CascadeType 값은 다음과 같습니다.
- ALL: 모든 작업 (생성, 수정, 삭제 등)을 전파합니다.
- PERSIST: 생성 작업만 전파합니다.
- MERGE: 수정 작업만 전파합니다.
- REMOVE: 삭제 작업만 전파합니다.
- REFRESH: 새로 고침 작업만 전파합니다.
- DETACH: 분리 작업만 전파합니다.
- Hibernate Envers: Hibernate Envers는 엔티티의 변경 이력을 추적하고 관리하는 데 사용되는 라이브러리입니다. Envers를 사용하면 엔티티의 변경 이력을 감사하고, 특정 시점의 엔티티 상태를 복원할 수 있습니다.
- Lombok: Lombok은 반복적인 코드를 줄여주는 Java 라이브러리입니다. @Getter, @Setter, @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor 등의 어노테이션을 사용하여 boilerplate 코드를 자동으로 생성할 수 있습니다.
- 빌더 패턴 (Builder Pattern): 빌더 패턴은 객체 생성을 더 유연하고 가독성 좋게 만들어주는 디자인 패턴입니다. 빌더 패턴을 사용하면 객체 생성 시 필요한 필드만 선택적으로 설정할 수 있습니다.
- Stream API: Stream API는 Java 8부터 도입된 기능으로, 컬렉션 데이터를 효율적으로 처리하기 위한 기능입니다. stream(), map(), filter(), collect() 등의 메서드를 사용하여 데이터를 변환하고 수집할 수 있습니다.
반응형