▪︎ 프로젝트 생성
start.spring.io

▪︎ Mybatis, H2 데이터베이스 설정
spring.application.name=lecture018
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
mybatis.mapper-locations=classpath:mappers/*.xml
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.jdbc-type-for-null=NULL
mybatis.type-aliases-package=com.example.lecture018
.
└── main/
├── java/
│ └── com/
│ └── example/
│ └── lecture018/
│ └── Lecture018Application.java
└── resources/
├── mappers
├── static
├── templates
├── application.properties
└── schema.sql
CREATE TABLE posts
(
id BIGINT AUTO_INCREMENT NOT NULL,
title VARCHAR(50) NOT NULL,
description VARCHAR(50) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
CREATE TABLE post_attachments
(
id BIGINT AUTO_INCREMENT NOT NULL,
post_id BIGINT NOT NULL,
origin_filename VARCHAR(255) NOT NULL,
stored_filename VARCHAR(50) NOT NULL,
content_type VARCHAR(30) NOT NULL,
file_size BIGINT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_post FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE
);
INSERT INTO posts(title, description) VALUES('Avengers', 'Avengers: Infinity War Official Trailer...');
▪︎ 게시물 조회 API 구현
.
└── main/
├── java/
│ └── com/
│ └── example/
│ └── lecture018/
│ ├── post/
│ │ ├── controller/
│ │ │ └── PostController.java
│ │ ├── dto/
│ │ │ ├── PostAttachmentDto.java
│ │ │ └── PostDto.java
│ │ ├── repository/
│ │ │ └── PostMapper.java
│ │ └── service/
│ │ ├── PostService.java
│ │ └── PostServiceImpl.java
│ └── Lecture018Application.java
└── resources/
├── mappers/
│ └── PostMapper.xml
├── static
├── templates
├── application.properties
└── schema.sql
package com.example.lecture018.post.dto;
import lombok.Data;
import java.time.LocalDate;
import java.util.List;
@Data
public class PostDto {
private long id;
private String title;
private String description;
private LocalDate createdAt;
private List<PostAttachmentDto> attachments;
}
package com.example.lecture018.post.dto;
import lombok.Data;
import java.time.LocalDate;
@Data
public class PostAttachmentDto {
private long id;
private long postId;
private String originFilename;
private String storedFilename;
private String contentType;
private long fileSize;
private LocalDate createdAt;
}
package com.example.lecture018.post.repository;
import com.example.lecture018.post.dto.PostDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface PostMapper {
List<PostDto> findAllPosts();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<mapper namespace="com.example.lecture018.post.repository.PostMapper">
<resultMap id="postResultMap" type="PostDto">
<id property="id" column="id"/>
<result property="title" column="title"/>
<result property="description" column="description"/>
<result property="createdAt" column="post_created_at"/>
<collection property="attachments" ofType="PostAttachmentDto">
<result property="id" column="attachment_id"/>
<result property="postId" column="post_id"/>
<result property="originFilename" column="origin_filename"/>[
<result property="storedFilename" column="stored_filename"/>
<result property="contentType" column="content_type"/>
<result property="fileSize" column="file_size"/>
<result property="createdAt" column="attachment_created_at"/>
</collection>
</resultMap>
<select id="findAllPosts" resultMap="postResultMap">
SELECT p.id,
p.title,
p.description,
p.created_at AS post_created_at,
pa.id AS attachment_id,
pa.post_id,
pa.origin_filename,
pa.stored_filename,
pa.content_type,
pa.file_size,
pa.created_at AS attachment_created_at
FROM posts p
LEFT OUTER JOIN post_attachments pa ON p.id = pa.post_id
</select>
</mapper>
package com.example.lecture018.post.service;
import com.example.lecture018.post.dto.PostDto;
import java.util.List;
public interface PostService {
List<PostDto> getPosts();
}
package com.example.lecture018.post.service;
import com.example.lecture018.post.dto.PostDto;
import com.example.lecture018.post.repository.PostMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class PostServiceImpl implements PostService {
private final PostMapper postMapper;
@Override
public List<PostDto> getPosts() {
return postMapper.findAllPosts();
}
}
package com.example.lecture018.post.controller;
import com.example.lecture018.post.dto.PostDto;
import com.example.lecture018.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class PostController {
private final PostService postService;
@GetMapping("/posts")
public ResponseEntity<List<PostDto>> getPosts() {
return ResponseEntity.ok(postService.getPosts());
}
}
▪︎ 게시물 첨부파일 조회 API 구현
package com.example.lecture018.post.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.example.lecture018.post.dto.PostAttachmentDto;
import com.example.lecture018.post.dto.PostDto;
@Mapper
public interface PostMapper {
List<PostDto> findAllPosts();
PostAttachmentDto findPostAttachmentById(long id);
}