
src/main/java/ohahsis/dailydirector/note/domain/Note.java
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "note")
public class Note extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long note_id;
private String title;
private Boolean status; // 노트 완결 여부
@Size(max = 4)
private Set<String> contents = new HashSet<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id")
private User user;
@OneToMany(mappedBy = "note", cascade = CascadeType.ALL)
private Set<NoteHashtag> noteHashtags = new HashSet<>();
}
Note 와 InnerNote(현 contents) 에 대한 고민src/main/java/ohahsis/dailydirector/note/domain/Hashtag.java
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "hashtag")
public class Hashtag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long hashtag_id;
private String name;
@OneToMany(mappedBy = "hashtag", cascade = CascadeType.ALL)
private Set<NoteHashtag> noteHashtags = new HashSet<>();
}
src/main/java/ohahsis/dailydirector/note/domain/NoteHashtag.java
@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "note_hashtag")
public class NoteHashtag {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long note_hashtag_id;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "note_id")
private Note note;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "hashtag_id")
private Hashtag hashtag;
}
cascade 설정 관련 오류가 발생했다. 자세한 내용은 다음 문서를 참고하자.NoteHashtag 는 데이터 테이블로써 독립적으로 존재하고, Hashtag의 속성을 여러개 가지는 게 아니라 종합적인 정보를 담은 튜플을 여러 개 가지는 형식이 된다.src/main/java/ohahsis/dailydirector/note/dto/request/NoteSaveRequest.java
@Data
public class NoteSaveRequest {
// @NotBlank(message = "내용을 입력해주세요.")
private Set<String> contents;
private Boolean status;
private String title;
private Set<String> hashtagNames;
}
src/main/java/ohahsis/dailydirector/note/dto/response/NoteSaveResponse.java
@Data
@AllArgsConstructor
public class NoteSaveResponse {
private Long note_id;
}
src/main/java/ohahsis/dailydirector/note/infrastructure/NoteRepository.java
@Repository
@Transactional(readOnly = true)
public interface NoteRepository extends JpaRepository<Note, Long> {
}
src/main/java/ohahsis/dailydirector/note/infrastructure/HashtagRepository.java
@Repository
@Transactional(readOnly = true)
public interface HashtagRepository extends JpaRepository<Hashtag, Long> {
@Transactional
Boolean existsByName(String name);
}
src/main/java/ohahsis/dailydirector/note/infrastructure/NoteHashtagRepository.java
@Repository
@Transactional(readOnly = true)
public interface NoteHashtagRepository extends JpaRepository<NoteHashtag, Long> {
}
NoteHashtag 또한 명확하게 분리된 하나의 기능이기 때문에 별도의 리포지토리를 생성한다.src/main/java/ohahsis/dailydirector/note/NoteConstants.java
public class NoteConstants {
public static final int CONTENTS_MAX_SIZE = 4;
}
src/main/java/ohahsis/dailydirector/note/application/NoteService.java
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteService {
private final NoteRepository noteRepository;
private final NoteHashtagRepository noteHashtagRepository;
private final HashtagRepository hashtagRepository;
@Transactional
public NoteSaveResponse save(NoteSaveRequest request) {
// 제목과 내용이 모두 없는 경우
if (request.getContents().isEmpty() || request.getTitle().isBlank()) {
throw new NoteSaveInvalidException(ErrorType.NOT_BLANK_ERROR);
}
// 기승전결 외 5개 이상의 문서 저장 요청이 온 경우
if (request.getContents().size() > CONTENTS_MAX_SIZE) {
throw new NoteSaveInvalidException(ErrorType.CONTENTS_MAX_SIZE_4);
}
/**
* 노트 저장
*/
var note = Note.builder()
.contents(request.getContents())
.status(request.getStatus())
.title(request.getTitle())
.build();
var savedNote = noteRepository.save(note);
/**
* 해시태그 저장
*/
for (String name : request.getHashtagNames()) {
if(!hashtagRepository.existsByName(name)) {
var hashtag = Hashtag.builder()
.name(name)
.build();
hashtagRepository.save(hashtag);
}
}
/**
* 노트 해시태그 저장
*/
for (String name : request.getHashtagNames()) {
Hashtag hashtag = Hashtag.builder()
.name(name)
.build();
var noteHashtag = NoteHashtag.builder()
.note(note)
.hashtag(hashtag)
.build();
noteHashtagRepository.save(noteHashtag);
}
return new NoteSaveResponse(savedNote.getNote_id());
}
}
추후 해시태그 서비스를 분리하는 것을 고려해보자.
src/main/java/ohahsis/dailydirector/note/presentation/NoteController.java
@RestController
@RequestMapping(path = "/api/notes", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class NoteController {
private final NoteService noteService;
@PostMapping
public ResponseEntity<?> createNote(AuthUser user, @RequestBody NoteSaveRequest noteRequest) {
var response = noteService.save(noteRequest);
return ResponseDto.created(response);
}
}