본문 바로가기
Back-end/Spring Boot + REST API

Spring boot - blog application (REST API) : Post CRUD

by javapp 자바앱 2022. 6. 29.
728x90

REST API 를 통해 게시물을 CRUD - 

Create(생성), Read(읽기), Update(갱신), Delete(삭제) 적용

 

 

 

패키지 구조

 

 

application.properties

spring.datasource.dbcp2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/myblog?userSSL=false&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
spring.datasource.username = root
spring.datasource.password = root

# hibernate properties
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto= update

 

 

Creating JPA Entity

JPA 를 통해 데이터베이스 테이블 생성

@Data // getter setter requiredArgsConstructor toString
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="posts", uniqueConstraints = {@UniqueConstraint(columnNames= {"title"})})
public class Post 
{
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	@Column(name="title", nullable=false)
	private String title;
	@Column(name="description", nullable=false)
	private String description;
	@Column(name="content", nullable=false)
	private String content;
}

 

MySQL posts 테이블 생성

 

 

Creating JPA Repository

//We don't need to @Repository annotation to this interface 
//because the JpaRepository interface has an implementation
//SimpleJpaRepository internally annotated with @Repository annotation and @Transactional
public interface PostRepository extends JpaRepository<Post, Long>
{
	
}

 

 

Creating Custom Exception

사용자 정의 예외 처리

/* This is cause Spring boot to respond with the specified HTTP status code
 * whenever this exception is thrown from your controller. */
@ResponseStatus(value= HttpStatus.NOT_FOUND)
@Getter
public class ResourceNotFoundException extends RuntimeException
{
	 private String resourceName;
	 private String fieldName;
	 private long fieldValue;
	 
	public ResourceNotFoundException(String resourceName, String fieldName, long fieldValue) {
		super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
		this.resourceName = resourceName;
		this.fieldName = fieldName;
		this.fieldValue = fieldValue;
	}
}

 

HTTP status code의 NOT_FOUND 에러 발생시 ResourceNotFoundException 처리, 해당 클래스 호출

2022-06-27 10:54:14.299  WARN 2232 --- [nio-8080-exec-4] .w.s.m.a.ResponseStatusExceptionResolver : Resolved [com.springboot.blog.exception.ResourceNotFoundException: Post not found with id : '6']

 

 

Creating DTO Class

클라이언트에 데이터를 보여주기 위함.

@Data
public class PostDto 
{
	private long id;
	private String title;
	private String description;
	private String content;
}

 

 

 

 

Service interface

public interface PostService 
{
	public PostDto createPost(PostDto postDto);
	
	public List<PostDto>getAllPosts();
	
	public PostDto getPostById(Long id);
	
	public PostDto updatePost(PostDto postDto, Long id);
	
	public void deletePostById(Long id);
}

 

Service

@Service
public class PostServiceImpl implements PostService
{
	private PostRepository postRepository;
	
	// inject
	public PostServiceImpl(PostRepository postRepository) {
		this.postRepository = postRepository;
	}
	
	@Override
	public PostDto createPost(PostDto postDto) {
		
		// convert DTO to entity
		Post post = mapToEntity(postDto);
		
		Post newPost  =postRepository.save(post);
		
		// convert entity to DTO
		PostDto postResponse = mapToDTO(newPost);
		
		return postResponse;
	}

	@Override
	public List<PostDto> getAllPosts() {
		List<Post> posts= postRepository.findAll();
		return posts.stream().map(post -> mapToDTO(post)).collect(Collectors.toList());
	}
	
	
	// convert DTO to entity
	private Post mapToEntity(PostDto postDto)
	{
		Post post = new Post();
		post.setTitle(postDto.getTitle());
		post.setDescription(postDto.getDescription());
		post.setContent(postDto.getContent());
		return post;
	}
	
	// convert entity to DTO
	private PostDto mapToDTO(Post post)
	{
		PostDto postdto = new PostDto();
		postdto.setId(post.getId());
		postdto.setTitle(post.getTitle());
		postdto.setDescription(post.getDescription());
		postdto.setContent(post.getContent());
		return postdto;
	}

	@Override
	public PostDto getPostById(Long id) {
		Post post = postRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Post", "id", id));
		return mapToDTO(post);
	}

	@Override
	public PostDto updatePost(PostDto postDto, Long id) {
		
		Post post = postRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Post", "id", id));
		post.setTitle(postDto.getTitle());
		post.setDescription(postDto.getDescription());
		post.setContent(postDto.getContent());
		
		return mapToDTO(postRepository.save(post));
	}

	@Override
	public void deletePostById(Long id) {
		Post post = postRepository.findById(id).orElseThrow(()->new ResourceNotFoundException("Post", "id", id));
		postRepository.delete(post);
	}
}

 

 

Controller

더보기

@RestController
@RequestMapping("/api/posts")
public class PostController 
{
private PostService postService;

// if you are configuring a class as a spring bean and it has only one constructor,
// then we can omit @Autowired annotation
public PostController(PostService postService) {
this.postService = postService;
}

@GetMapping
public List<PostDto> getAllPosts() {
return postService.getAllPosts();
}

@PostMapping
public ResponseEntity<PostDto> createPost(@RequestBody PostDto postDto){
return new ResponseEntity<>(postService.createPost(postDto),HttpStatus.CREATED);
}

// get post by id
@GetMapping("/{id}")
public ResponseEntity<PostDto> getPostById(@PathVariable(name= "id") long id){
return ResponseEntity.ok(postService.getPostById(id));
}

// update post by id rest api
@PutMapping("/{id}")
public ResponseEntity<PostDto> updatePost(@RequestBody PostDto postDto, @PathVariable(name="id") long id){
PostDto postResponse = postService.updatePost(postDto, id);
return new ResponseEntity<>(postResponse,HttpStatus.OK);

}

// delete post by id rest api
@DeleteMapping("/{id}")
public ResponseEntity<String> deletePost(@PathVariable Long id)
{
postService.deletePostById(id);
return new ResponseEntity<>("삭제 완료",HttpStatus.OK);
}

}

 

Create

@PostMapping
public ResponseEntity<PostDto> createPost(@RequestBody PostDto postDto){
    return new ResponseEntity<>(postService.createPost(postDto),HttpStatus.CREATED);
}

 

 

 

 

Read

All Read

@GetMapping
public List<PostDto> getAllPosts() {
    return postService.getAllPosts();
}

 

post by id

// get post by id
@GetMapping("/{id}")
public ResponseEntity<PostDto> getPostById(@PathVariable(name= "id") long id){
    return ResponseEntity.ok(postService.getPostById(id));
}

 

 

 

Update

// update post by id rest api
@PutMapping("/{id}")
public ResponseEntity<PostDto> updatePost(@RequestBody PostDto postDto, @PathVariable(name="id") long id){
    PostDto postResponse = postService.updatePost(postDto, id);
    return new ResponseEntity<>(postResponse,HttpStatus.OK);
}

 

 

Delete

// delete post by id rest api
@DeleteMapping("/{id}")
public ResponseEntity<String> deletePost(@PathVariable Long id)
{
    postService.deletePostById(id);
    return new ResponseEntity<>("삭제 완료",HttpStatus.OK);
}

 

 

해당 아이디가 없을 때

댓글