implementation 'org.modelmapper:modelmapper:3.1.0'
@Configuration
public class RootConfig {
//@Bean을 통해 ModelMapper 객체를 스프링 컨테이너에 빈으로 등록
@Bean
public ModelMapper getMapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration()
.setFieldMatchingEnabled(true)
//소스와 대상 객체간 필드 이름을 기준으로 매핑 -> 즉 필드 이름 일치 시 자동으로 매핑
.setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
//기본적으로 ModelMapper는 public 필드만 매핑에 사용하나, private 필드도 매핑에 쓰겠단 얘기
.setMatchingStrategy(MatchingStrategies.STRICT);
//매핑시 정확한 일치만 허용(교재는 LOOSE)
return modelMapper;
}
}
등록 작업 처리
@Service
@Log4j2
@RequiredArgsConstructor
@Transactional //일관성을 유지하고 글 등록에서 예외가 발생했을때 롤백시키기 위해 트랜잭션 처리를 해줌
public class BoardServiceImpl implements BoardService{
private final ModelMapper modelMapper;
private final BoardRepository boardRepository;
@Override
public Long register(BoardDTO boardDTO) {
Board board = modelMapper.map(boardDTO, Board.class); //modelMapper의 특성을 이용해서 BoardDTO 객체를 Board 객체로 변환
Long bno = boardRepository.save(board).getBno();
return bno;
}
조회 작업 처리
@Override
public BoardDTO readOne(Long bno) {
//Optional<> 타입으로 리턴하여 result에 저장
Optional<Board> result = boardRepository.findById(bno);
Board board = result.orElseThrow(); //Optional 객체가 비어있을때 예외를 던짐
BoardDTO boardDTO = modelMapper.map(board, BoardDTO.class);
return boardDTO;
}
수정 작업 처리
@Override
public void modify(BoardDTO boardDTO) {
Optional<Board> result = boardRepository.findById(boardDTO.getBno());
Board board = result.orElseThrow();
//Board 클래스에 정의되어있는 change 메서드의 Title과 Content만 가져옴
board.change(boardDTO.getTitle(), boardDTO.getContent());
boardRepository.save(board);
}
//테스트 할 때는 반드시 실제 데이터베이스에 존재하는 번호를 이용해서 확인
@Test
public void testModify() {
//변경에 필요한 데이터만
BoardDTO boardDTO = BoardDTO.builder()
.bno(101L)
.title("Updated....101")
.content("Updated content 101...")
.build();
boardService.modify(boardDTO);
}
삭제 작업 처리
@Override
public void remove(Long bno) {
boardRepository.deleteById(bno);
}
PageRequestDTO, PageResponseDTO와 같이 클래스를 작성 후 반환 타입은 PageResponseDTO로 활용
PageRequestDTO
페이징 관련 정보(page/size) 및 검색의 종류(type)와 키워드(keyword)를 지정
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageRequestDTO {
@Builder.Default
private int page = 1;
@Builder.Default
private int size = 10;
private String type; // 검색의 종류 t,c, w, tc,tw, twc
private String keyword;
//현재 검색 조건들을 BoardRepository에서 String[]로 처리하기 때문에 type이라는 문자열을 배열로 반환해주는 기능
public String[] getTypes(){
if(type == null || type.isEmpty()){
return null;
}
return type.split("");
}
//페이징 처리를 위해 Pageable 타입을 반환하는 기능
public Pageable getPageable(String...props) {
return PageRequest.of(this.page -1, this.size, Sort.by(props).descending());
}
//Spring Data JPA는 페이지 번호를 1부터 시작하도록 기본 설정되어 있습니다. 그래서 PageRequest.of 메서드에 전달되는 this.page - 1는 내부적으로 페이지 번호를 1부터 시작하는 인덱스로 조정하는 역할을 합니다.
//따라서 1페이지는 0이고 2페이지는 1.. 이런 식으로 인덱싱되는것