크게 id와 title, introduce, user, serialState, genre가 있다.
title은 소설의 제목, introduce는 소설의 설명문이며 serialState는 연재 유무, genre는 장르이다.
여기서 크게 소설 엔티티를 만들고 하위로 각 장르별 엔티티를 만들까 고민했지만, 장르가 다르다고 내용이 크게 달라지는 것이 아니고 장르만 달라지는 것이기에 장르를 enum으로 만들기로 했다.
user의 경우 각 소설의 작가를 의미한다. user 한 명당 소설이 아예 없을 수도 혹은 여러개 있을 수도 있기에 소설의 관점에서 보면 user는 ManyToOne이다. 그러므로 @ManyToOne을 넣고 fetch는 Lazy로 설정한다. 소설을 조회할 때 유저도 같이 조회할 필요는 없기 때문이다.
사실 이 점이 의문이긴 한데. 소설을 조회할 때 유저도 같이 조회해도 상관없지 싶으나, 큰 서비스 같은 경우는 관계가 복잡하게 되어 있는 경우가 많으니까...
그리고 JoinColimn으로 유저 id하고 연결해주면 된다. 이때 name은 user의 밖에서 보이는 이름으로 해줘야 한다(Column에서 설정한 이름).
소설 등록, 삭제, id로 찾기, 전체 조회 기능을 구현했다.
일단 등록 기능의 이름은 create로 영속성 엔티티 메니저인 em에서 persist로 영속성 관리를 하게 했다. 그리고 아이디를 반환한다.
삭제는 delete로 아이디를 받아서 findOne을 이용해 객체를 찾은 다음에 remove로 삭제하도록 했다.
id로 소설 찾기는 findOne인데, em.find를 이용해서 id를 가지고 Novel 클래스를 찾도록 했다.
소설 전체 조회는 findAll로 쿼리를 날려서 전체 값을 리스트로 찾는 기능이다.
시버스는 단순히 레파지토리에 위임하는 기능으로 createNovel, deleteNovel, findNovels, findOne이 있다. 레파지토리의 기능을 불러오기만 하면 된다.
각 장르에는 modernFantasy, RomanceFantasy, BL을 넣어줬다.
연재 중인지 완결인지를 구분하는 enum으로 Live와 Finish가 있다.
일단 유저를 등록하고 소설을 등록한다. 그리고 등록한 소설과 레파지토리에서 해당 소설 아이디로 찾은 소설이 유사한지 확인한다.
@Test
public void 소설등록() throws Exception{
//Given
User user = new User();
user.setName("A");
Long userId = userService.join(user);
//When
Novel novel = new Novel();
novel.setTitle("악녀한테 너무해!");
novel.setGenre(Genre.RomanceFantasy);
novel.setSerialState(SerialState.Live);
novel.setUser(user);
Long novelId = novelService.createNovel(novel);
//Then
assertEquals(novel, novelRepository.findOne(novelId));
}
유저를 등록하고 소설을 등록한 다음에 해당 소설을 삭제한다. 그리고 등록한 소설과 해당 소설 아이디로 레파지토리에서 찾은 소설이 같은지 확인한다. 이때는 값이 같으면 안 되니 테스트에 문제가 있어야 한다.
참고로 말하자면 단순히 삭제한 소설을 찾기만 하면 테스트를 통과한다. 왜냐하면 레파지토리에서 null을 찾아오기 때문이다. 밑의 테스트 코드에 문제가 생겨서 테스트가 바르게 된 이유는 해당 소설과 찾아온 null값이 다르기 때문이다. 레파지토리가 삭제한 소설 id로 null을 찾아 왔으니 소설이 잘 삭제되었다고 말할 수 있다.
@Test
public void 소설삭제() throws Exception{
//Given
User user = new User();
user.setName("A");
Long userId = userService.join(user);
//When
Novel novel = new Novel();
novel.setTitle("악녀한테 너무해!");
novel.setGenre(Genre.RomanceFantasy);
novel.setSerialState(SerialState.Live);
novel.setUser(user);
Long novelId = novelService.createNovel(novel);
novelService.deleteNovel(novelId);
//Then
assertEquals(novel, novelRepository.findOne(novelId));
}
비교 결과
엔티티 삭제를 찾아보던 중 사람들이 DAO를 사용하는 것을 보고 DAO가 무엇인지 의문을 가지게 되었다. 객체들을 관리한다는 점에서 레파지토리랑 비슷한 거 같은데... 정확한 차이가 뭘까?
간단하게 말하자면 DAO란 DB 관련 로직들을 모아둔 객체이고 그래서 sql이 그렇게 많았나 레파지토리는 엔티티 객체를 보관하고 관리하는 저장소이다. 사실 둘이 거의 비슷하다고 한다. 나는 처음 배울 때부터 레파지토리로 배웠으니 일단은 레파지토리를 이용해서 개발을 계속 할 예정이다.
참고 링크, https://www.inflearn.com/questions/111159/domain%EA%B3%BC-repository-%EC%A7%88%EB%AC%B8