▪︎ 프로젝트 생성

start.spring.io

image.png

▪︎ 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);
}