프로젝트 기능을 크게 3가지로 나눴고, 그 중 여행지 검색과 여행지 상세 페이지 부분 구현을 맡게 되었다. 해당 기능 구현을 위해서 먼저 관련 엔티티들 간의 관계를 설정했다.

여행지 검색 기능과 여행지 상세 페이지 기능은 리뷰 기능과 높은 관련성을 가지고 있다. 검색 기능의 경우 태그 검색 기능이 구현되어야 한다. 또한 기본적인 여행지 페이지 정렬이 리뷰 갯수로 정렬이 되어야 한다. 따라서 여행지 검색 시 리뷰 데이터와 해당 리뷰들의 태그 정보를 가져와야 한다.
따라서 여행지 엔티티 뿐만 아니라 리뷰/태그 엔티티까지 개발을 진행했다.
추후에 아래 엔티티들에 필요한 메서드를 (비즈니스 / 조회 메서드) 추가할 예정이다. 현재는 기본적인 엔티티의 골격만 작성했다.
여행지를 소개해주는 기능이기 때문에 이미지가 필요했다. 하지만 많은 이미지가 필요할 것이라고 생각했기 때문에 서버에 이미지를 저장하는 형태가 아닌 S3에 이미지를 저장하고 URL 형태로 이미지를 사용하고자 했다. 따라서 특정 여행지는 여러개의 이미지 URL을 가지고 있어야 했다.
추후 여행지 검색 페이지에서 마음에 드는 여행지를 장바구니에 담을 수 있도록 해야 한다. 이를 위해서 카카오 맵 API에서 사용되는 필드를 추가했다. 또한 여행 계획 설계 페이지에서는 DAMDA 사이트에서 만든 여행지 외에도 다양한 장소를 장바구니에 추가할 수 있도록 했다. 따라서 직접 만든 여행지 데이터와 사용자가 임의로 추가한 장소를 구분할 수 있는 값이 필요했다.
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Spot {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "spot_name", nullable = false)
private String name;
@Column(name = "spot_city", nullable = false)
private String city;
@Column(name = "spot_address")
private String address;
@Column(name = "spot_description", columnDefinition = "TEXT")
private String description;
@OneToMany(mappedBy = "spot")
@Builder.Default
private List<SpotImage> spotImageURLList = new ArrayList<>();
@OneToMany(mappedBy = "spot")
@Builder.Default
private List<Review> reviewList = new ArrayList<>();
@Column(name = "spot_review_cnt", nullable = false)
private int reviewCnt = 0;
private long urlId;
private String x;
private String y;
private String selfMadeFlag;
}
여행지의 이미지가 저장된 URL의 정보를 담고 있는 엔티티이다.
기본 필드
URL : AWS S3의 이미지 저장 장소
연관관계 필드
spot : 해당 여행지
출처 - (인프런, 김연한님 강의) 실전! 스프링 부트와 JPA 활용1 강의자료 참고
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SpotImage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "spot_image_url", nullable = false)
private String URL = "";
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "spot_id")
private Spot spot;
}
자바 8 이상부터는 하이버네이트가 자동으로 날짜타입으로 인식하므로 별도의 어노테이션 필요 X
추후 회원 로그인 기능이 개발되면 회원 엔티티와도 관계 설정 필요
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "review_title", nullable = false)
private String title;
@Column(name = "review_content", nullable = false, columnDefinition = "TEXT")
private String content;
@Column(name = "review_travel_start_date")
private LocalDateTime start_date;
@Column(name = "review_travel_end_date")
private LocalDateTime end_date;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "spot_id")
private Spot spot;
@OneToMany(mappedBy = "review")
@Builder.Default
private List<ReviewTag> reviewTagList = new ArrayList<>();
}
리뷰와 태그의 관계는 다대다 관계이다. 따라서 중간에 별도의 리뷰 태그 테이블을 만들어야 한다.
기본 필드
id : PK
연관관계 필드
review : 태그가 사용된 리뷰들
tag : 리뷰에 사용된 태그들
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReviewTag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "review_id")
private Review review;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "tag_id")
private Tag tag;
}
기본 필드
id : PK
name : 태그명
연관관계 필드
reviewTagList : 해당 태그가 사용된 리뷰들
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Tag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "tag_name")
private String name;
@OneToMany(mappedBy = "tag")
@Builder.Default
private List<ReviewTag> reviewTagList = new ArrayList<>();
}