받은 쪽지함 entity 받은 쪽지함 entity
처음 테이블을 만들 때 하나의 테이블로 받은 쪽지와 보낸 쪽지를 관리하는 게 좋다고 생각했었다.
하지만 하나에 테이블에서 관리하게 되면 보낸 사람이 보낸 쪽지를 삭제하게 되면 받은 사람의 쪽지도 같이 삭제되기 때문
테이블을 분리해야겠다고 생각했다.
@Entity
@Setter
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class MessageReceive {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "MESSAGE_RECEIVE_NO")
private Long messageReceiveNo; //기본키
private String messageReceiveTitle;
private String messageReceiveContent;
private String messageReceiveDate;
private String sendMemberId;
private String receiveMemberId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
public void addMessageReceive(Member member) {
this.member = member;
member.getMessageReceive().add(this);
}
public MessageReceive( String messageReceiveTitle, String messageReceiveContent, String messageReceiveDate, String sendMemberId, String receiveMemberId) {
this.messageReceiveTitle = messageReceiveTitle;
this.messageReceiveContent = messageReceiveContent;
this.messageReceiveDate = messageReceiveDate;
this.sendMemberId = sendMemberId;
this.receiveMemberId = receiveMemberId;
}
}
↑
받은 쪽지함 entity
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
@Entity
@Setter
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class)
public class MessageSend {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "MESSAGE_SEND_NO")
private Long messageSendNo; //기본키
private String messageSendTitle;
private String messageSendContent;
private String messageSendDate;
private String sendMemberId;
private String receiveMemberId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
public void addMessageSendMember(Member member) {
this.member = member;
member.getMessageSend().add(this);
}
public MessageSend( String messageSendTitle, String messageSendContent, String messageSendDate, String sendMemberId, String receiveMemberId) {
this.messageSendTitle = messageSendTitle;
this.messageSendContent = messageSendContent;
this.messageSendDate = messageSendDate;
this.sendMemberId = sendMemberId;
this.receiveMemberId = receiveMemberId;
}
}
↑
보낸 쪽지함 entity
import Healthduo.demo.dto.MessageSendDTO;
import Healthduo.demo.service.BbsService;
import Healthduo.demo.service.MessageService;
import Healthduo.demo.web.TransferDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttribute;
@Slf4j
@Controller
@RequiredArgsConstructor
public class MessageController {
private final TransferDTO transferDTO;
private final BbsService bbsService;
private final MessageService messageService;
@GetMapping("messagemenu")
public String messageMenu() {
log.info("messageMenu(controller start)");
return "message/menu";
}
@GetMapping("messagesend")
public String messageSend(Model model) {
log.info("messageSend(controller start)");
MessageSendDTO messageSendDTO = new MessageSendDTO();
model.addAttribute("messageSendDTO", messageSendDTO);
return "message/send";
}
//메시지 저장 매핑
@PostMapping("messagesave")
public String messageSave(@RequestParam("receiveMemberId") String receiveMemberId,
@RequestParam("messageSendTitle") String messageSendTitle,
@RequestParam("messageSendContent") String messageSendContent,
@SessionAttribute(name = "memberId", required = false) String loginMember) {
log.info("messagesave(controller start)");
int resultMessageSave = messageService.messageSave(receiveMemberId, messageSendTitle, messageSendContent,loginMember);
return "/message/menu";
}
}
↑
초기에 만든 controller로 메시지 저장 매핑 메서드
messageSerive.messageSave(...)에서 예외가 발생하면 에러 메시지 별로
html이나 javascript 같은 view를 따로 만들어줘야 에러메시지를 보여줄 수 있을거같아
fetch api로 비동기 통신을 통해 alert으로 표현해주는게 더 간단하고 좋을 거 같아 restcontroller로 변경했다.
따라서
import Healthduo.demo.service.BbsService;
import Healthduo.demo.service.MessageService;
import Healthduo.demo.web.TransferDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.SessionAttribute;
@RestController
@RequiredArgsConstructor
@Slf4j
public class MessageRestController {
private final TransferDTO transferDTO;
private final BbsService bbsService;
private final MessageService messageService;
@PostMapping("messagesave")
public String messageSave(@RequestParam("receiveMemberId") String receiveMemberId,
@RequestParam("messageSendTitle") String messageSendTitle,
@RequestParam("messageSendContent") String messageSendContent,
@SessionAttribute(name = "memberId", required = false) String loginMember) {
log.info("messagesave(controller start)");
String message = "";
try {
messageService.messageSave(receiveMemberId, messageSendTitle, messageSendContent,loginMember);
}catch (Exception e){
log.info("message={}" ,e.getMessage());
message = e.getMessage();
}
return message;
}
}
↑
이와 같이 restcontroller로 바꿔주고 message 그대로를 반환해주어
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="board/layout/basic">
<head th:replace="fragments/header :: header"/>
<body>
<div id="justify-content" class="container">
<div th:replace="fragments/bodyHeader :: bodyHeader"/>
<form class="form-horizontal" th:action="@{/messagesave}" th:object="${messageSendDTO}" method="post">
<input type="hidden" th:if="*{messageSendNo != null and messageSendNo > 0}" th:field="*{messageSendNo}"/>
<div class="form-group">
<label th:for="bbs_title" class="col-sm-2 control-label">받는 사람</label>
<div class="col-sm-10">
<input type="text" id="receiveMemberId" th:field="*{receiveMemberId}" class="form-control"
placeholder="받는 사람을 입력해주세요."/>
</div>
</div>
<div class="form-group">
<label th:for="messageSendTitle" class="col-sm-2 control-label">제목</label>
<div class="col-sm-10">
<input type="text" id="messageSendTitle" th:field="*{messageSendTitle}" class="form-control"
placeholder="제목을 입력해 주세요."/>
</div>
</div>
<div class="form-group">
<label th:for="messageSendContent" class="col-sm-2 control-label">내용</label>
<div class="col-sm-10">
<textarea id="messageSendContent" th:field="*{messageSendContent}" class="form-control"
placeholder="내용을 입력해 주세요."></textarea>
</div>
</div>
<div class="btn_wrap text-center">
<a th:href="@{/bbsLists}" class="btn btn-default waves-effect waves-light">뒤로가기</a>
<button type="button" onclick="sendMessage()" class="btn btn-primary waves-effect waves-light">저장하기</button>
</div>
</form>
<div th:replace="fragments/footer :: footer"/>
</div>
</body>
<script type="text/javascript">
async function sendMessage() {
let receiveMemberId = document.getElementById("receiveMemberId").value;
let messageSendTitle = document.getElementById("messageSendTitle").value;
let messageSendContent = document.getElementById("messageSendContent").value;
let URL = "http://localhost:8080/messagesave"
alert(receiveMemberId);
let options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
receiveMemberId: receiveMemberId,
messageSendTitle: messageSendTitle,
messageSendContent: messageSendContent
})
}
let response = await fetch(URL, options)
let text = await response.text();
if (text == "받는 사람 아이디가 존재하지 않습니다." ||
text == "쪽지 제목을 입력해주세요." ||
text == "쪽지 내용을 입력해주세요.") {
alert(text);
} else {
location.href = "http://localhost:8080/messagemenu"
}
}
</script>
</html>
에러에 따라 메시지가 출려되고 에러가 발생하지 않으면 메시지를 저장하도록 구현했다.
↑
아이디를 입력하지 않거나 없는 회원 아이디를 입력했을 경우(가장 우선적으로 체킹 한다.)
↑
제목을 입력하지 않았을 경우 (두 번째로 체킹 한다.)
↑
내용을 입력하지 않았을 경우 (마지막으로 체킹 한다.)
import Healthduo.demo.domain.Member;
import Healthduo.demo.domain.MessageReceive;
import Healthduo.demo.domain.MessageSend;
import Healthduo.demo.repository.MemberRepository;
import Healthduo.demo.repository.MessageReceiveRepository;
import Healthduo.demo.repository.MessageSendRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class MessageServiceImpl implements MessageService{
private final MemberRepository memberRepository;
private final MessageSendRepository messageSendRepository;
private final MessageReceiveRepository messageReceiveRepository;
@Override
public void messageSave(String receiveMemberId, String messageSendTitle, String messageSendContent, String loginMember) {
log.info("messageSave(Service start)");
Optional<Member> findReciveMemberId = memberRepository.findById(receiveMemberId);
CheckError(messageSendTitle, messageSendContent, findReciveMemberId);//오류 검증 기능
Optional<Member> SendMemberInfo = memberRepository.findById(loginMember);
MessageSend messageSend = new MessageSend(receiveMemberId, messageSendContent, String.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))), loginMember, receiveMemberId);
messageSend.addMessageSendMember(SendMemberInfo.get());
messageSendRepository.save(messageSend);
MessageReceive messageReceive = new MessageReceive(receiveMemberId, messageSendContent, String.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))), loginMember, receiveMemberId);
messageReceive.addMessageReceive(SendMemberInfo.get());
messageReceiveRepository.save(messageReceive);
}
private void CheckError(String messageSendTitle, String messageSendContent, Optional<Member> findReciveMemberId) {
if(findReciveMemberId.isEmpty()){
throw new RuntimeException("받는 사람 아이디가 존재하지 않습니다.");
}
if(messageSendTitle.isBlank()){
throw new RuntimeException("쪽지 제목을 입력해주세요.");
}
if(messageSendContent.isBlank()){
throw new RuntimeException("쪽지 내용을 입력해주세요.");
}
}
}
↑
비즈니스 로직으로 받는 사람 아이디가 존재하는지 select로 조회하고 CheckError 메서드를 통해
아이디와 제목과 내용을 확인한다. 만약 예외가 발생하면 트랜잭션을 종료시킨다.
RuntimeException으로 예외를 발생시킨 이유는
RuntimeException는 Unchecked Exception으로 에러를 잡아주지 않아도 컴파일러에서 문제가 생기지
않는다.
만약 예외가 발생하면 controller에서 catch 하여 에러 메시지를 view에 보낸다.