[번들러 프로젝트] Card의 정보를 수정할 때 Category를 수정할 시 문제

이혜지·2023년 2월 24일
0

Bundler PJT

목록 보기
1/5
post-custom-banner

1. 문제


들어가기에 앞서..

첫번째. 우리의 디비를 먼저 보자.

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 으로 매핑은 해줬지만,

실제로 사용하는건 feedIdcategoryId 이다.

두번째. 그럼 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가 있는것이다.

하지만 . . . . . . . . . . .. 아래에서 계속

2. 고민


큰 문제가 발생했다. 바로 카드의 정보를 수정할 때 변경할 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;

}

해결방법을 고민해봤다.

  1. 일단 중분류와 대분류를 구분할 필요 없이, 그냥 객체를 다 삭제하고 다시 생성하는 방법
    1. Feed Id 1번이 수정요청이 들어오면 feedCategoryRepository.findByFeedId(feedId) 를 통해 FeedId 1번을 가지고있는 모든 FeedCategory 객체를 받아온다.
    2. 해당 List의 사이즈만큼 돌면서(어차피 최대 두개임) FeedCategory 객체를 삭제
    3. DTO에서 받아온 categoryFirstId,categorySecondId 두개로 FeedCategory 객체를 두개 생성한다.
  2. parent 가 null 이면 대분류고 아니면 중분류!!!!!!!!!!!!!! ← 유레카. 디비만 보다보니까 parent의 존재를 까먹고있엇다 …

3. 결론


조회시에 FeedCategory에서 피드의 아이디를 가지고 카테고리 아이디를 검색하고,

카테고리가 부모라면 부모 + 자식 같이 주고

카테고리가 자식이라면 자식만 준다.

profile
공유 문화를 지향하는 개발자입니다.
post-custom-banner

0개의 댓글