본문 바로가기

생각정리/사이드 프로젝트

사이드 프로젝트 : 중고 거래 플랫폼 - 타임스탬프, MariaDB, 순환 참조

트러블 슈팅


타임스탬프의 데이터 입력이 안 되는 경우

@Getter
// 부모 클래스로 선언해 상속 시켜 사용할 때 사용
@MappedSuperclass
// JPA Entity에 이벤트가 발생할 관련 코드를 실행
@EntityListeners(AuditingEntityListener.class)
public abstract class TimeStamp {

    @CreatedDate
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime created_at;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    private LocalDateTime updated_at;
}
  • 문제 발생 : TimeStamp 엔티티를 만들고 사용하기 위한 엔티티들에 상속을 시켜 생성될 때 시간과 마지막 수정 시간을 자동으로 입력되도록 추가해 사용을 하는데 상속받은 엔티티가 생성될 때, timestamp 데이터가 null 값으로 입력됨.
  • 문제 해결 : @EntityListeners로 이벤트를 받기 위해서는 메인 Application에 @EnableJpaAuditing을 사용해주어야 자동으로 값을 등록할 수 있다.

마리아 DB 한글 안 들어가 짐

평소에는 MySQL을 계속 사용해 몰랐지만, MariaDB의 경우는 기본 설정이 달랐다.

  • 문제 발생 : MariaDB를 생성하고 사용하는데 한글로 된 데이터를 넣을 경우 인코딩 에러를 발생시키며 한글이 들어가지 않음
  • 문제 해결 : MariaDB의 경우 데이터 베이스 생성 시 schema collate가 latin1로 되어 있어 MySQL에서 사용한 utf8로 수정하고 테이블 재생성
// 스키마 확인 쿼리
SELECT schema_name, default_character_set_name FROM information_schema.schemata;
// utf8로 된 collate아 많아 버전을 보고 선택 할 것
alter schema maria_db collate utf8mb3_croatian_ci;

인텔리제이 데이터베이스에서 스키마 설정 수정

순환 참조 발생

게시글에서도 카테고리 정보가 필요하고 카테고리에서도 게시글의 정보가 필요해 양방향 매핑으로 엔티티를 구성

 

문제 발생 : 게시글의 정보를 불러올 때, 양방향 매핑으로 인한 순환 참조로 인한 오류 발생

문제 파악 : 게시글과 카테고리는 N:1 관계로 양쪽에서 사용할 일 이 있어 단방향으로 사용할 수 없다. 그래서 DTO사용해서 구현했지만, 게시글 정보만 따로 가져오고 카테고리를 따로 들고 와서 엔티티로 넣어서 사용 중이었어서 순환 참조로 인한 오류 발생

문제 해결 : 카테고리도 따로 DTO를 만들어서 사용함으로 순환 참조 해결

@Getter
@NoArgsConstructor
public class BoardResponseDto {
    private Long id;
    private String title;
    private String contents;
    private int price;
    private int boardLike;
    private boolean active;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    private CategoryResponseDto category;

    public BoardResponseDto(Board board) {
        this.id = board.getId();
        this.title = board.getTitle();
        this.contents = board.getContents();
        this.price = board.getPrice();
        this.boardLike = board.getBoard_like();
        this.active = board.isActive_yn();
        this.createdAt = board.getCreated_at();
        this.updatedAt = board.getUpdated_at();
        this.category = new CategoryResponseDto(board.getCategory());
    }
}
순환 참조를 방지하는 방법

1. @JsonIgnore
JSON 데이터에 해당 프로퍼티를 null로 들어가게 만들어 데이터를 아예 포함시키지 않는다.

2. @JsonManagedReference 와 JsonBackReference
부모 클래스의 엔티티의 필드에 @JsonManagedReference를 이용해 순환 참조를 막을 수 있다.
자식 클래스의 엔티티의 필드에 @JsonBackReference를 이용해 순환 참조를 막을 수 있다.

3. @JsonIgnoreProperties
부모 클래스의 엔티티의 필드에 @JsonIgnoreProperties({"순환참조를 막을 엔티티"}) 를 이용해 순환 참조를 막을 수 있다.

4. DTO 사용
엔티티 자체를 response로 사용하지 않고 dto를 이용해 response의 데이터를 정제해서 순환 참조를 막을 수 있다.

5. 단방향 매핑
엔티티 양쪽에서 접근할 필요가 없다면 단방향 매핑으로 순환 참조를 막을 수 있다.