오늘은 한 번 개인과제를 도전해봤다.
- 1단계 : 일정 CRU
🔻 조건
- 일정을 저장, 단건 조회, 수정할 수 있습니다.
- 일정은
작성 유저명,할일 제목,할일 내용,작성일,수정일필드를 갖고 있습니다.
아직 연관관계를 하지 않아서 금방할 수 있을 것 같다.
기본적인 설정부터 시작! application.properties에 추가
spring.datasource.url=jdbc:mysql://localhost:3306/todo
spring.datasource.username=root
spring.datasource.password="비밀번호"
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true
entity, dto, 3 Layer Architecture(controller, service, repository) 패키지를 생성하고 class와 interface를 생성한다.
먼저 Entity 패키지에 들어가는 class를 생성
update메서드는 Todo 엔티티의 필드 값을 업데이트한다.
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "Todo")
public class Todo extends Timestamped{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false)
private String username;
@Column(name = "title", nullable = false)
private String title;
private String content;
public Todo(TodoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.title = requestDto.getTitle();
this.content = requestDto.getContent();
}
public void update(TodoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.title = requestDto.getTitle();
this.content = requestDto.getContent();
}
}
JPA Auditing을 이용하여 객체가 생성된 시간이 저장된 createdAt와, 객체의 값을 변경할 때 변경된 시간이 저장된 modifiedAt 필드 생성
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {
@CreatedDate
@Column(updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime createdAt;
@LastModifiedDate
@Column
@Temporal(TemporalType.TIMESTAMP)
private LocalDateTime modifiedAt;
}
그 다음 dto패키지에 class 생성
@Getter
public class TodoRequestDto {
private String username;
private String title;
private String content;
}
@Getter
public class TodoResponseDto {
private Long id;
private String username;
private String title;
private String content;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
public TodoResponseDto(Todo todo) {
this.id = todo.getId();
this.username = todo.getUsername();
this.title = todo.getTitle();
this.content = todo.getContent();
this.createdAt = todo.getCreatedAt();
this.modifiedAt = todo.getModifiedAt();
}
}
이젠 controller, service, repository를 만들다
@RestController
@RequestMapping("/api")
public class TodoController {
private final TodoService todoService;
public TodoController(TodoService todoService) {
this.todoService = todoService;
}
@PostMapping("/todo")
public ResponseEntity<TodoResponseDto> createTodo(@RequestBody TodoRequestDto requestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(todoService.createTodo(requestDto));
}
@GetMapping("/todo/{id}")
public ResponseEntity<TodoResponseDto> getTodo(@PathVariable Long id) {
return ResponseEntity.status(HttpStatus.OK).body( todoService.getTodo(id));
}
@PutMapping("/todo/{id}")
public ResponseEntity<TodoResponseDto> updateTodo(@PathVariable Long id, @RequestBody TodoRequestDto requestDto) {
return ResponseEntity.status(HttpStatus.OK).body(todoService.updateTodo(id, requestDto));
}
}
@Service
public class TodoService {
private final TodoRepository todoRepository;
public TodoService(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
@Transactional
public TodoResponseDto createTodo(TodoRequestDto requestDto) {
// RequestDto -> Entity
Todo todo = new Todo(requestDto);
// DB 저장
Todo newtodo = todoRepository.save(todo);
// Entity -> ResponseDto
TodoResponseDto todoResponseDto = new TodoResponseDto(newtodo);
return todoResponseDto;
}
public TodoResponseDto getTodo(Long id) {
// 해당하는 일정이 있는지 확인
Todo todo = findTodo(id);
TodoResponseDto todoResponseDto = new TodoResponseDto(todo);
return todoResponseDto;
}
@Transactional
public TodoResponseDto updateTodo(Long id, TodoRequestDto requestDto) {
// 해당하는 일정이 있는지 확인
Todo todo = findTodo(id);
// Entity 업데이트
todo.update(requestDto);
// 변경된 일정 DB 저장
todoRepository.save(todo);
TodoResponseDto todoResponseDto = new TodoResponseDto(todo);
return todoResponseDto;
}
private Todo findTodo(Long id) {
return todoRepository.findById(id).orElseThrow(() ->
new IllegalArgumentException("선택한 일정은 존재하지 않습니다."));
}
}
Spring Data JPA에서 제공하는 기본 리포지토리 인터페이스인 JpaRepository를 상속받는다.
public interface TodoRepository extends JpaRepository<Todo, Long> {
}
잘 실행이 된다.