[SpringBoot] 1대1 질문 만들기

이민준·2021년 8월 24일
0

우선 User와 1대1질문 그리고 1대1질문 첨부파일 엔티티를 만들어줍니다.
각 엔티티에 CascadeType.Remove를 추가해서 user가 회원탈퇴할 때 1대1질문이나 파일들이 같이 삭제될 수 있도록 만들어줍니다.

User Entity

public class User {
	@Id
	@Column(name = "USER_UUID")
	private String userUuid;

	@JsonIgnore
	private String password;

	@OneToMany(mappedBy = "user",  cascade = {CascadeType.REMOVE},fetch = FetchType.LAZY)
	@JsonIgnoreProperties({"user"})
	private List<Inquiry> inquiry;

	@Column(name = "CREATE_DATE")
	private LocalDateTime createDate;

}

1대1질문 Entity

public class Inquiry {

    @Id
    @SequenceGenerator(name = "INQUIRY_SEQ_GENERATOR", sequenceName = "INQUIRY_SEQUENCE", allocationSize = 1, initialValue = 20000)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INQUIRY_SEQ_GENERATOR")
    @Column(name = "INQUIRY_ID")
    private Long id;

    @JsonIgnoreProperties({"inquiry"})
    @JoinColumn(name = "USER_UUID")
    @ManyToOne
    private User user;

    @JsonIgnoreProperties({"inquiry"})
    @OneToMany(mappedBy = "inquiry", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
    private List<Inquiry_file> inquiry_file;
}

첨부 파일 Entity

public class Inquiry_file {

    @Id
    @SequenceGenerator(name = "INQUIRY_FILE_SEQ_GENERATOR", sequenceName = "INQUIRY_FILE_SEQUENCE", allocationSize = 1, initialValue = 20000)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INQUIRY_FILE_SEQ_GENERATOR")

    @Column(name = "INQUIRY_FILE_ID")
    private Long id;

    @Column(name = "INQUIRY_FILE_URL")
    private String url;

    @Column(name = "INQUIRY_FILE_TYPE")
    private String type;

    @Column(name = "INQUIRY_FILE_NAME")
    private String name;

    @Column(name = "INQUIRY_FILE_SIZE")
    private Long size;

    @ManyToOne
    @JoinColumn(name = "INQUIRY_ID")
    @JsonIgnoreProperties({"inquiry_file"})
    private Inquiry inquiry;

}

이제 서비스 로직을 만듭니다

1대1질문 생성


    @Transactional
    public Inquiry createInquiry(CreateInquiryDto createInquiryDto, PrincipalDetails principalDetails) {
        List<MultipartFile> fileList = createInquiryDto.getFileList();
        Optional<User> userOptional = userRepository.findByEmail(principalDetails.getEmail());
        User userEntity= userOptional.get();
        Inquiry inquiry =
                Inquiry.builder()
                        .user(userEntity)
                        .content(createInquiryDto.getContent())
                        .status(createInquiryDto.getStatus())
                        .title(createInquiryDto.getTitle())
                        .type(createInquiryDto.getType())
                        .build();
        inquiryRepository.save(inquiry);

        for(int i=0; i<createInquiryDto.getFileList().size(); i++){
            String fileName = UUID.randomUUID().toString() + "_" + createInquiryDto.getFileList().get(i).getOriginalFilename();
            Path imageFilePath = Paths.get(uploadFolder + fileName);
            Inquiry_file inquiry_file = Inquiry_file.builder()
                    .name(createInquiryDto.getFileList().get(i).getOriginalFilename().replaceFirst("[.][^.]+$", "")) // 확장자 지우기
                    .size(createInquiryDto.getFileList().get(i).getSize())
                    .url(fileName)
                    .type(createInquiryDto.getFileList().get(i).getContentType())
                    .inquiry(inquiry)
                    .build();
            try {
                Files.write(imageFilePath, createInquiryDto.getFileList().get(i).getBytes());
            } catch (Exception e) {
                e.printStackTrace();
            }
            inquiryFileRepository.save(inquiry_file);
        }
        return inquiry;
    }

DTO로 전달된 inquriy는 그대로 save하고 filelist size만큼 for문을 돌면서 inquiry_file table에 row를 하나씩 쌓아줍니다. 이미지 이름이 중복되었을 경우, 덮어써질 수 도 있으므로 앞에 UuId를 붙여서 만들어줍니다. 또한 프론트에서 이미지 이름을 보여주므로 확장자를 뗀 순수 이미지 이름만을 따로 칼럼으로 저장합니다.

1대1질문 첨부파일 확인

    @GetMapping(value="/inquiry/attachment")
    public ResponseEntity<Resource> attachment(@Param("filename") String filename){
        String temp = path;
        Path filePath = null;
        filePath = Paths.get(temp+filename);
        HttpHeaders header = new HttpHeaders();
        Tika tika = new Tika();
        String mimeType;
        try {
                mimeType = tika.detect(filePath);
                header.add("Content-Type", mimeType);
        } catch (Exception e) {

        }

        Resource resource = new FileSystemResource(filePath);
        return new ResponseEntity<Resource>(resource,header, HttpStatus.OK);
    }

아래 포스트맨으로 잘 나오는것을 확인할 수 있습니다

이때 동영상 파일이 스프링 부트에서 약 1mb로 제한이 걸려있는데, application.properties 아래 설정으로 해결이 가능합니다.

spring.servlet.multipart.maxFileSize=8MB
spring.servlet.multipart.maxRequestSize=8MB

1대1문의 수정

1대1 문의 수정 로직도 create랑 비슷합니다. 단지 해당 질문이 유저가 만든 질문인지 한번 확인하고 기존 질문의 첨부파일은 삭제하고 새로 만들어주면 됩니다.
이 때, 바뀌는 부분만 프론트가 보내주는게 아니라 전체 데이터를 다시 보내주어야합니다.

    @Transactional
    public String modify(@AuthenticationPrincipal PrincipalDetails principalDetails, ModifyInquiryDto modifyInquiryDto ) {

        List<Long> inquiryIdList = inquiryRepository.findAllIdByUserUuid(principalDetails.getUserUuid());
        if (!inquiryIdList.contains(modifyInquiryDto.getId())) {
            return "유저가 생성한 질문이 아닙니다.";
        }

        Optional<UserMaster> userMasterOptional = userRepository.findByUserUuid(principalDetails.getUserUuid());
        UserMaster userMaster = userMasterOptional.get();
        Optional<Inquiry> inquiryOptional = inquiryRepository.findByInquiryId(modifyInquiryDto.getId());
        Inquiry inquiry = inquiryOptional.get();
        inquiry.setUserMaster(userMaster);

        // 기존의 파일 스토리지에서 delete
        for(int i =0; i < inquiry.getInquiry_file().size(); i++) {
            String url = inquiry.getInquiry_file().get(i).getUrl();
            Path filePath = Paths.get(uploadFolder + url);
            try {
                Files.delete(filePath);
            } catch (NoSuchFileException e) {
                System.out.println("삭제하려는 파일이 없습니다");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 새로 만들기
        for(int i=0; i<modifyInquiryDto.getFileList().size(); i++){
            String fileName = UUID.randomUUID().toString() + "_" + modifyInquiryDto.getFileList().get(i).getOriginalFilename();
            Path imageFilePath = Paths.get(uploadFolder + fileName);
            Inquiry_file inquiry_file = Inquiry_file.builder()
                    .name(modifyInquiryDto.getFileList().get(i).getOriginalFilename().replaceFirst("[.][^.]+$", ""))
                    .size(modifyInquiryDto.getFileList().get(i).getSize())
                    .url(fileName)
                    .type(modifyInquiryDto.getFileList().get(i).getContentType())
                    .inquiry(inquiry)
                    .build();
            try {
                Files.write(imageFilePath, modifyInquiryDto.getFileList().get(i).getBytes());

            } catch (Exception e) {
                e.printStackTrace();
            }
            inquiryFileRepository.save(inquiry_file);
        }
        return "True";
    }
profile
러닝커브가 장점인 개발자입니다.

0개의 댓글