원래 목표는 crud 다 구현하려 했으나 뒤에서 언급할 controller 작업에서 시간이 꽤 잡아먹혔습니다.
사실 delete문은 작성하기 어렵지는 않으나 delete된 데이터를 다른 테이블로 백업하는 구조를 생각중이고 (적용 안할수도 있음), update문은 node.js (클라이언트) 와 오가는 정보를 좀더 구상하고 작성할 생각입니다..
// repository
사실 repository는 user, board, comment 셋 다 create와 read만 구현되어있기에 특이사항으로 언급할만한 점이 없다고 생각합니다.
원래대로라면 인터페이스를 만들고 구현하는 형식으로 제작, 확장성을 염두해 두었어야 했는데 그 사실을 service를 만드는 도중에 깨달아버렸습니다. 리팩토링이 어려운 부분은 아니라 생각하니 추후에 리팩토링 할 예정이고, 다음 프로젝트부터는 초기부터 인터페이스에 신경을 써서 제작을 해야 할 것 같습니다.
UserRepository
@Repository
@RequiredArgsConstructor
public class UserRepository {
private final EntityManager em;
public void save(User user) {
em.persist(user);
}
public User findOne(Long id) {
return em.find(User.class, id);
}
public List<User> findByEmail(String email) {
return em.createQuery("select u from User u where u.email = :email", User.class)
.setParameter("email", email)
.getResultList();
}
public List<User> findByNickname(String nickname) {
return em.createQuery("select u from User u where u.nickname = :nickname", User.class)
.setParameter("nickname", nickname)
.getResultList();
}
}
findByEmail은 계정생성과 로그인 기능에서, findByNickname은 계정생성 기능에서 사용됩니다.
BoardRepository
@Repository
@RequiredArgsConstructor
public class BoardRepository {
private final EntityManager em;
final int limit = 30;
public void save(Board board) {
em.persist(board);
}
public Board findOne(Long id) {
return em.find(Board.class, id);
}
public List<Board> getIdFromPage(int page) {
return em.createQuery("select b from Board b order by b.id desc", Board.class)
.setFirstResult(limit * (page - 1))
.setMaxResults(limit)
.getResultList();
}
}
node.js 에서 게시글의 갯수에 따른 페이지 기능이 구현되어있으므로, limit 상수를 수정함으로서 반환될 최대 게시글 수를 조정하도록 만들었습니다.
board 와 comment 의 양방향 연관관계에 따른 성능이슈가 있을지 잘 모르겠습니다.
CommentRepository
@Repository
@RequiredArgsConstructor
public class CommentRepository {
private final EntityManager em;
public void save(Comment comment) {
em.persist(comment);
}
public Comment findOne(Long id) {
return em.find(Comment.class, id);
}
}
음, 사실 findOne 메서드는 comment를 단일 조회할 일이 없을것 같아서 빼도 될것같긴 합니다.
board와 양방향 연관관계로 이루어져 따로 조회가 필요하지 않아보여 생성기능만 만들었습니다.
// service
service 와 repository 항목이 한 글에 작성된 이유, service도 딱히 언급할 것이 별로 없습니다.
생성, 조회 기능 뿐인 미완성이라 추후에 두 항목은 기능을 더 추가해서 언급되기를.
service 단계에서 테스트케이스를 만들어 검증을 했어야했는데 만드는데 정신이 팔려 테스트를 따로 치루지 못했습니다.
때문에 기능 작동은 controller를 통해 테스트를 했으며, 다행히 service 코드의 오류는 없었습니다.
다음번엔 테스트케이스를 좀더 의식해서 만들어보는 습관을 길러야 할 것 같습니다.
UserService
@Service
@Transactional
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
@Transactional
public Long join(User user) {
validateDuplicateUser(user);
userRepository.save(user);
return user.getId();
}
private void validateDuplicateUser(User user) {
List<User> findEmail = userRepository.findByEmail(user.getEmail());
if (!findEmail.isEmpty()) {
throw new IllegalStateException("이미 가입되어있는 email 입니다.");
}
List<User> findNickname = userRepository.findByNickname(user.getNickname());
if (!findNickname.isEmpty()) {
throw new IllegalStateException("중복된 닉네임 입니다.");
}
}
public User Login(String email, String password) {
List<User> findEmail = userRepository.findByEmail(email);
if (findEmail.isEmpty()) {
throw new IllegalStateException("가입되지 않은 이메일 주소 입니다.");
}
if (!findEmail.get(0).getPassword().equals(password)) {
throw new IllegalStateException("패스워드가 일치하지 않습니다.");
}
return findEmail.get(0);
}
}
회원가입 기능 (을 위한 값 중복검사 기능) 과 로그인 기능을 가지고 있습니다.
문제가 있을 시 exception을 내며, 해당 문제가 일어난 부분에 관한 텍스트를 만들어 줬습니다.
기능 작동은 controller 항목에서 보여드리겠습니다.
BoardService
@Service
@Transactional
@RequiredArgsConstructor
public class BoardService {
private final BoardRepository boardRepository;
private final UserRepository userRepository;
@Transactional
public Long create(Board board, Long userId) {
User user = userRepository.findOne(userId);
board.setUser(user);
boardRepository.save(board);
return board.getId();
}
public Board findOne(Long id) {
return boardRepository.findOne(id);
}
public List<Board> getIdFromPage(int page) {
return boardRepository.getIdFromPage(page);
}
}
사실상 create 메서드를 제외하면 repository에서 직접 호출해도 될 것 같습니다.
CommentService
@Service
@Transactional
@RequiredArgsConstructor
public class CommentService {
private final CommentRepository commentRepository;
private final UserRepository userRepository;
private final BoardRepository boardRepository;
public Long create(String content, Long userId, Long boardId) {
User user = userRepository.findOne(userId);
Board board = boardRepository.findOne(boardId);
Comment comment = new Comment(user, board, content);
commentRepository.save(comment);
return comment.getId();
}
}
CommentRepository 에서 언급했던 것처럼 board 와 양방향 연관관계이기에 텅텅 비어있는 모습입니다. 물론 수정, 삭제가 들어가긴 해야겠지만.
'프로젝트' 카테고리의 다른 글
토이프로젝트 - NodeToSpring 4. 리팩토링 약간... (0) | 2022.12.13 |
---|---|
토이프로젝트 - NodeToSpring 3. controller (0) | 2022.12.04 |
토이프로젝트 - NodeToSpring 1. entity 설계 (0) | 2022.12.04 |
spring - 댓글 기능 (0) | 2022.10.07 |
Node.js - 게시판 ( 게시물 및 댓글 작성 / 삭제 ) (0) | 2022.09.07 |