들어가기에 앞서..
첫번째. 우리의 디비를 먼저 보자.
Feed는 Category를 가질 수 있다. Category는 여러개의
Feed는 대분류 중분류의 카테고리를 가진다.
다대다 관계를 1:N N:1 관계로 풀어낸 형태.
디비의 모양은 이렇지만 Jpa 매핑을 또 확인할 필요가 있다.
db erd
Feed.class
public class Feed {
@Builder.Default
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "feed_id")
private List<FeedCategory> feedCategoryList;
}
Feed는 일대다 관계로 FeedCategory의 목록을 가지고 있다.
= List<FeedCategory> feedCategoryList
Category.class
public class Category implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "category_id")
private Long categoryId;
@Column(name = "category_name")
private String categoryName;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "category_parent_id", referencedColumnName = "category_id")
private Category parent;
@OneToMany(mappedBy = "parent") //셀프의 연관관계를 건거라고 생각하면 된다.
private List<Category> child = new ArrayList<>();
//==연관관계 편의 메서드==// parent니까 셀프
public void addChildCategory(Category child) {
this.child.add(child);
child.setParent(this);
}
@Builder
public Category(String categoryName, Category parent) {
this.categoryName = categoryName;
this.parent = parent;
}
}
Category에서는 조회할 필요가 없으므로 없다. 즉 1:N 단방향 관계
FeedCategory.class
public class FeedCategory {
@Column(name = "feed_id")
private Long feedId;
@Column(name = "category_id")
private Long categoryId;
@ManyToOne(cascade = CascadeType.ALL, fetch = LAZY)
@JoinColumn(name = "category_id")
private Category category;
}
여기서 보면 매핑은 @ManyToOne
으로 매핑은 해줬지만,
실제로 사용하는건 feedId
와 categoryId
이다.
두번째. 그럼 Card객체를 생성할때 어떻게 FeedCategory 객체도 생성해주는가?
@Builder
패턴을 이용하여 Card객체를 생성한다.
**CardSaveRequestDto.class
설명: 카드를 생성하기위해 앞단에서 카드 정보를 받아오는 Dto**
public class CardSaveRequestDto {
//문제, 일반, 링크를 한번에 받는다
@NotEmpty
private Long userId;
private User writer;
@NotEmpty
private String feedType;
@NotEmpty
private String feedTitle;
private String feedContent;
@NotEmpty
private Long categoryFirstId; //대분류 중분류에 들어갈 피드의 카테고리 Id
private Long categorySecondId;
@NotEmpty
private String cardType;
private String cardDescription;
private String cardCommentary;
private Long feedId;
public Card toEntity(User writer) {
return Card.builder()
.writer(writer)
.feedTitle(this.feedTitle)
.feedContent(this.feedContent)
.cardType(CardType.valueOf(this.cardType))
.cardDescription(this.cardDescription)
.cardCommentary(this.cardCommentary)
.build();
}
}
여기서는 category의 정보를 넣어 줄 수 없다.
참고로 Feed = Card임!
그래서 CardService.class
에서 객체를 생성할 때, FeedCategory의 객체를 따로 생성해줬다.
**CardService.class**
public class CardService {
private final CardRepository cardRepository;
private final FeedRepository feedRepository;
private final UserRepository userRepository;
private final FeedCategoryRepository feedCategoryRepository;
private final CardBundleRepository cardBundleRepository;
@Transactional
public Long saveCard(CardSaveRequestDto requestDto) {
User writerUser = userRepository.findById(requestDto.getUserId()).orElseThrow(() ->
new IllegalArgumentException("해당 유저가 존재하지 않습니다. userId= " + requestDto.getUserId()));
Long savedFeedId = cardRepository.save(requestDto.toEntity(writerUser)).getFeedId();
//카테고리 넣어주기
saveFeedCategory(savedFeedId, requestDto.getCategoryFirstId());
if (requestDto.getCategorySecondId() != null) {
saveFeedCategory(savedFeedId, requestDto.getCategorySecondId());
}
return savedFeedId;
}
//먼저 카드의 정보만 객체로 생성하여 생성된 Card객체의 Id를 반환받으면
//이를 FeedCategory에 해당 CardId와 해당되는
//카테고리(앞단에서 받아온)의 대분류 중분류를 넣어 생성해줬따. -> 총 두번까지 생성할 수 있음.
//FeedCategory 객체 생성 -> 여기서 객체를 생성함
@Transactional
public void saveFeedCategory(Long feedId, Long categoryId) {
feedCategoryRepository.save(
FeedCategory.builder()
.feedId(feedId)
.categoryId(categoryId)
.build());
}
}
이렇게 생성하는 문제를 해결했다.
이렇게 되면,
Feed를 생성하고 해당 카테고리를 지정하면
FeedCategory 에는 FeedId, CategoryId가 있는것이다.
하지만 . . . . . . . . . . .. 아래에서 계속
큰 문제가 발생했다. 바로 카드의 정보를 수정할 때 변경할 CategoryId가 들어온다면, 원래 FeedCategory객체에서 뭘 수정해야할지 모른다는것!!!! 뭐가 대분류고 뭐가 중분류일까 ?!!? 1?!!!!! 1
일단 수정할시 앞단에서 받아오는 Dto는 아래 코드
**CardUpdateRequest.class**
@Data
public class CardUpdateRequestDto {
@NotEmpty
private String feedTitle;
private String feedContent;
@NotEmpty
private Long categoryFirstId; //대분류
private Long categorySecondId;//중분류 -> 변경을 안하면 원래 카테고리의 번호를 다시 보낸다.
private String cardDescription;
private String cardCommentary;
}
해결방법을 고민해봤다.
feedCategoryRepository.findByFeedId(feedId)
를 통해 FeedId 1번을 가지고있는 모든 FeedCategory 객체를 받아온다. categoryFirstId
,categorySecondId
두개로 FeedCategory 객체를 두개 생성한다.조회시에 FeedCategory에서 피드의 아이디를 가지고 카테고리 아이디를 검색하고,
카테고리가 부모라면 부모 + 자식 같이 주고
카테고리가 자식이라면 자식만 준다.