https://velog.io/@mooh2jj/todoList-프로젝트-설명
내에서 TodoList backend 리팩토링을 진행해보았습니다. 그전 코드는 이 블로그를 참조하면 됩니다.
TodoEntity
BaseTimeEntity
추가
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "Todo")
public class TodoEntity extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(name = "todoOrder", nullable = false)
private Long order;
@Column(nullable = false)
private Boolean completed;
}
BaseTimeEntity
createdDate
, modifiedDate
가 Table에 들어갑니다.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity { //추상화 클래스로 만들고 Posts 클래스가 상속받도록 한다.
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
}
따로 main 어플리케이션 클래스에 @EnableJpaAuditing
을 설정하는 것도 잊으면 안됩니다!
Dto(TodoRequest, TodoResponse)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TodoRequest {
private String title;
private Long order;
private Boolean completed;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TodoResponse {
private Long id;
private String title;
private Long order;
private Boolean completed;
}
TodoService, TodoServiceImpl 로 나누었습니다.
TodoService
mapToDto
, mapToEntity
메서드로 Dto - Entity 변환을 Service 단에서 해결했습니다.
public interface TodoService {
// 추가
TodoResponse add(TodoRequest todoRequest);
// 조회
TodoResponse searchById(Long id);
// 전체 조회
List<TodoResponse> searchAll();
// update1
TodoResponse updateById(Long id);
// update2
TodoResponse updateById(Long id, TodoRequest request);
// 삭제
void deleteById(Long id);
// 전체 삭제
void deleteAll();
}
TodoServiceImpl
@Service
@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService{
public final TodoRepository todoRepository;
@Override
public TodoResponse add(TodoRequest todoRequest) {
TodoEntity todoEntity = mapToEntity(todoRequest);
todoRepository.save(todoEntity);
TodoResponse todoResponse = mapToDto(todoEntity);
return todoResponse;
}
private TodoResponse mapToDto(TodoEntity todoEntity) {
return TodoResponse.builder()
.id(todoEntity.getId())
.title(todoEntity.getTitle())
.order(todoEntity.getOrder())
.completed(todoEntity.getCompleted())
.build();
}
// add method refactoring
private TodoEntity mapToEntity(TodoRequest todoRequest) {
return TodoEntity.builder()
.title(todoRequest.getTitle())
.order(todoRequest.getOrder())
.completed(todoRequest.getCompleted())
.build();
}
@Override
public TodoResponse searchById(Long id) {
var byId = todoRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
return mapToDto(byId);
}
@Override
public List<TodoResponse> searchAll() {
var all = todoRepository.findAll();
return all.stream()
.map(TodoEntity -> mapToDto(TodoEntity))
.collect(Collectors.toList());
}
@Override
public TodoResponse updateById(Long id) {
var todoEntity = todoRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
todoEntity.setCompleted(true);
return mapToDto(todoRepository.save(todoEntity));
}
@Override
public TodoResponse updateById(Long id, TodoRequest request) {
var todoEntity = todoRepository.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
if (request.getTitle() != null) {
todoEntity.setTitle(request.getTitle());
}
if (request.getOrder() != null) {
todoEntity.setOrder(request.getOrder());
}
if (request.getCompleted() != null) {
todoEntity.setCompleted(request.getCompleted());
}
return mapToDto(todoRepository.save(todoEntity));
}
@Override
public void deleteById(Long id) {
todoRepository.deleteById(id);
}
@Override
public void deleteAll() {
todoRepository.deleteAll();
}
}
TodoController
ResponseEntity
를 사용하여 statusCode, body 컨트롤을 쉽게 제어하게 했습니다.
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/todo")
public class TodoController {
private final TodoService todoService;
@PostMapping
public ResponseEntity<TodoResponse> create(@RequestBody TodoRequest request) {
log.info("Create");
if (ObjectUtils.isEmpty(request.getTitle())) {
return ResponseEntity.badRequest().build();
}
if (ObjectUtils.isEmpty(request.getOrder())) {
request.setOrder(0L);
}
if (ObjectUtils.isEmpty(request.getCompleted())) {
request.setCompleted(false);
}
TodoResponse todoResponse = todoService.add(request);
return new ResponseEntity<>(todoResponse, HttpStatus.CREATED);
}
@GetMapping("{id}")
public ResponseEntity<TodoResponse> readOne(@PathVariable Long id) {
log.info("Read One");
TodoResponse todoResponse = todoService.searchById(id);
// return new ResponseEntity<>(todoResponse, HttpStatus.OK);
return ResponseEntity.ok(todoResponse);
}
@GetMapping
public List<TodoResponse> readAll() {
log.info("Read All");
return todoService.searchAll();
}
@PutMapping("{id}")
public ResponseEntity<TodoResponse> update(@PathVariable Long id) {
log.info("Update");
TodoResponse todoResponse = todoService.updateById(id);
return new ResponseEntity<>(todoResponse, HttpStatus.OK);
}
/* @PutMapping("{id}")
public ResponseEntity<TodoResponse> update2(@PathVariable Long id, @RequestBody TodoRequest request) {
log.info("Update2");
TodoResponse todoResponse = todoService.updateById(id, request);
return new ResponseEntity<>(todoResponse, HttpStatus.OK);
}*/
@DeleteMapping("{id}")
public ResponseEntity<String> deleteOne(@PathVariable Long id) {
log.info("Delete");
todoService.deleteById(id);
return new ResponseEntity<>("deleteOne successfully.", HttpStatus.OK);
}
@DeleteMapping
public ResponseEntity<?> deleteAll() {
log.info("Delete All");
todoService.deleteAll();
return new ResponseEntity<>("deleteAll successfully.", HttpStatus.OK);
}
}