

이해가 안되면 외워라.
위의 구조의 각 계층이 스프링 프로젝트에서 실제로 어떻게 상호작용하는지 머릿 속에 그려져야 한다.
간단한 프로젝트를 보고 머릿 속으로 각 계층의 상호작용을 그려보자.
추가로, 실무에서는 MSA 단위로 서비스를 개발하기 때문에
Eureka서버에 등록된 서버와의 통신을 어떻게하는지 알아야한다.다음에 알아보도록 하자
JPA에서 Entity는 데이터베이스의 테이블에 대응하는 클래스이다.
Entity를 생성했다면, 데이터베이스와 연동을 해야한다.
- 데이터베이스와 연동해보기
위의 게시글에 데이터베이스와 연동하는 법에 대해서 소개해보았으니, 참고하도록
package com.wara.store.Entity;
import javax.persistence.*;
import lombok.*;
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Builder
public class StoreEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long storeId;
String storeName;
String storePhone;
String storeSeller;
}
package com.wara.store.Repository;
import com.wara.store.Entity.StoreEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface StoreRepository extends JpaRepository<StoreEntity, Long> {
Boolean existsByStoreId(Long storeId); //storeId로 상점 존재 확인
Boolean existsByStoreSeller(String storeSeller); //상점 이름으로 상점 존재 확인
StoreEntity findByStoreId(Long storeId); //storeId는 고유하다.
List<StoreEntity> findByStoreSeller(String storeSeller); //storeSeller는 여러개의 store를 가질 수 있다.
}
package com.wara.store.DAO;
import com.wara.store.Entity.StoreEntity;
import org.springframework.stereotype.Repository;
import java.util.Map;
@Repository
public interface StoreDAO{
//상점 존재 여부 Exist
public Map<String, Object> existStoreById(Long storeId);
public Map<String, Object> existStoreBySeller(String storeSeller);
//seller가 갖는 상점 list
//상점 생성 Create
public Map<String, Object> createStore(StoreEntity storeEntity);
//상점 읽기 Read
public Map<String, Object> readStoreById(Long storeId);
public Map<String, Object> readStoreBySeller(String storeSeller);
//상점 업데이트 Update
public Map<String, Object> updateStoreById(StoreEntity storeEntity);
//상점 삭제 Delete
public Map<String, Object> deleteStore(Long storeId);
}
package com.wara.store.DAO;
import com.wara.store.Entity.StoreEntity;
import com.wara.store.Repository.StoreRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Repository
public class StoreDAOImpl implements StoreDAO{
//Alt + Shift + Enter로 StoreDAO interface의 method를 override
private final StoreRepository storeRepository;
public StoreDAOImpl(@Autowired StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
//Exist
@Override
public Map<String, Object> existStoreById(Long storeId) {
Map<String, Object> result = new HashMap<>();
if (storeRepository.existsByStoreId(storeId)) {
result.put("result", "success");
} else {
result.put("result", "fail");
}
return result;
}
@Override
public Map<String, Object> existStoreBySeller(String storeSeller) {
Map<String, Object> result = new HashMap<>();
if (storeRepository.existsByStoreSeller(storeSeller)) {
result.put("result", "success");
} else {
result.put("result", "fail");
}
return result;
}
//Create
@Override
public Map<String, Object> createStore(StoreEntity storeEntity) {
Map<String, Object> result = new HashMap<>();
storeRepository.save(storeEntity);
if (storeRepository.existsByStoreId(storeEntity.getStoreId())) {
result.put("result", "success");
} else {
result.put("result", "fail");
}
return result;
}
//Read
@Override
public Map<String, Object> readStoreById(Long storeId) {
Map<String, Object> result = new HashMap<>();
StoreEntity storeEntity = storeRepository.findByStoreId(storeId);
if (storeEntity == null) {
result.put("result", "fail");
} else {
result.put("result", "success");
result.put("data", storeEntity);
}
return result;
}
@Override
public Map<String, Object> readStoreBySeller(String storeSeller) {
Map<String, Object> result = new HashMap<>();
List<StoreEntity> storeEntities = storeRepository.findByStoreSeller(storeSeller);
if (storeEntities.isEmpty()) {
result.put("result", "fail");
} else {
result.put("result", "success");
result.put("dataList", storeEntities);
}
return result;
}
//Update
@Override
public Map<String, Object> updateStoreById(StoreEntity storeEntity) {
Map<String, Object> result = new HashMap<>();
StoreEntity oldStoreEntity = storeRepository.findByStoreId(storeEntity.getStoreId());
if (oldStoreEntity != null) {
storeEntity.setStoreId(Optional.ofNullable(storeEntity.getStoreId()).orElse(oldStoreEntity.getStoreId()));
storeEntity.setStoreName(Optional.ofNullable(storeEntity.getStoreName()).orElse(oldStoreEntity.getStoreName()));
storeEntity.setStorePhone(Optional.ofNullable(storeEntity.getStorePhone()).orElse(oldStoreEntity.getStorePhone()));
storeEntity.setStoreSeller(Optional.ofNullable(storeEntity.getStoreSeller()).orElse(oldStoreEntity.getStoreSeller()));
storeRepository.save(storeEntity);
result.put("result", "success");
} else {
result.put("result", "fail");
}
return result;
}
//Delete
@Override
public Map<String, Object> deleteStore(Long storeId) {
Map<String, Object> result = new HashMap<>();
StoreEntity storeEntity = storeRepository.findByStoreId(storeId);
if (storeEntity == null) {
result.put("result", "fail");
} else {
storeRepository.delete(storeEntity);
result.put("result", "success");
}
return result;
}
}
package com.wara.store.DTO;
import lombok.*;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class StoreDTO {
Long storeId;
String storeName;
String storePhone;
String storeSeller;
}
package com.wara.store.DTO;
import lombok.*;
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ResponseDTO {
String result;
Object data;
}
package com.wara.store.DTO;
import lombok.*;
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class SimpleResponseDTO {
String result;
}
package com.wara.store.Service;
import com.wara.store.DTO.*;
import com.wara.store.Entity.StoreEntity;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public interface StoreService {
//Exist
public SimpleResponseDTO existStoreById(Long storeId);
public SimpleResponseDTO existStoreBySeller(String storeSeller);
//Create
public SimpleResponseDTO createStore(StoreDTO storeDTO);
//Read
public ResponseDTO readStoreById(Long storeId);
public ResponseDTO readStoreBySeller(String storeSeller);
//이미지는 다른 서버에서 가져옴.
//Update
public SimpleResponseDTO updateStoreById(StoreDTO storeDTO);
//Delete
public SimpleResponseDTO deleteStore(Long storeId);
//기타 서비스
public StoreEntity toEntity(StoreDTO storeDTO);
public ResponseDTO toResponseDTO(Map<String, Object> resultMap);
public SimpleResponseDTO toSimpleResponseDTO(Map<String, Object> resultMap);
}
package com.wara.store.Service;
import com.wara.store.DAO.StoreDAO;
import com.wara.store.DTO.ResponseDTO;
import com.wara.store.DTO.SimpleResponseDTO;
import com.wara.store.DTO.StoreDTO;
import com.wara.store.Entity.StoreEntity;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
public class StoreServiceImpl implements StoreService{
private final StoreDAO storeDAO;
private final static Logger logger = LoggerFactory.getLogger(StoreServiceImpl.class);
public StoreServiceImpl(@Autowired StoreDAO storeDAO
) {
this.storeDAO = storeDAO;
}
//Exist
@Override
public SimpleResponseDTO existStoreById(Long storeId) {
Map<String, Object> resultMap = storeDAO.existStoreById(storeId);
SimpleResponseDTO simpleResponseDTO = toSimpleResponseDTO(resultMap);
return simpleResponseDTO;
}
@Override
public SimpleResponseDTO existStoreBySeller(String storeSeller) {
Map<String, Object> resultMap = storeDAO.existStoreBySeller(storeSeller);
SimpleResponseDTO simpleResponseDTO = toSimpleResponseDTO(resultMap);
return simpleResponseDTO;
}
//Create
@Override
public SimpleResponseDTO createStore(StoreDTO storeDTO) {
StoreEntity storeEntity = toEntity(storeDTO);
Map<String, Object> resultMap = storeDAO.createStore(storeEntity);
SimpleResponseDTO simpleResponseDTO = toSimpleResponseDTO(resultMap);
return simpleResponseDTO;
}
//Read
@Override
public ResponseDTO readStoreById(Long storeId) {
Map<String, Object> resultMap = storeDAO.readStoreById(storeId);
ResponseDTO responseDTO = toResponseDTO(resultMap);
return responseDTO;
}
@Override
public ResponseDTO readStoreBySeller(String storeSeller) {
Map<String, Object> resultMap = storeDAO.readStoreBySeller(storeSeller);
ResponseDTO responseDTO = toResponseDTO(resultMap);
return responseDTO;
}
//Update
@Override
public SimpleResponseDTO updateStoreById(StoreDTO storeDTO) {
StoreEntity storeEntity = toEntity(storeDTO);
Map<String, Object> existMap = storeDAO.existStoreById(storeDTO.getStoreId());
SimpleResponseDTO simpleResponseDTO;
if (existMap.get("result").equals("success")) {
Map<String, Object> resultMap = storeDAO.updateStoreById(storeEntity);
simpleResponseDTO = toSimpleResponseDTO(resultMap);
} else {
simpleResponseDTO = toSimpleResponseDTO(existMap);
}
return simpleResponseDTO;
}
//Delete
@Override
public SimpleResponseDTO deleteStore(Long storeId) {
Map<String, Object> resultMap = storeDAO.deleteStore(storeId);
SimpleResponseDTO simpleResponseDTO = toSimpleResponseDTO(resultMap);
return simpleResponseDTO;
}
//기타 서비스
@Override
public StoreEntity toEntity(@NotNull StoreDTO storeDTO) {
StoreEntity storeEntity = StoreEntity.builder()
.storeId(storeDTO.getStoreId())
.storeName(storeDTO.getStoreName())
.storeSeller(storeDTO.getStoreSeller())
.storePhone(storeDTO.getStorePhone())
.build();
return storeEntity;
}
@Override
public ResponseDTO toResponseDTO(@NotNull Map<String, Object> resultMap) {
ResponseDTO responseDTO;
if (resultMap.containsKey("data")) {
System.out.println("Data type: " + resultMap.get("data").getClass().getName());
StoreEntity storeEntity = (StoreEntity) resultMap.get("data");
StoreDTO storeDTO = StoreDTO.builder()
.storeId(storeEntity.getStoreId())
.storeName(storeEntity.getStoreName())
.storeSeller(storeEntity.getStoreSeller())
.storePhone(storeEntity.getStorePhone())
.build();
responseDTO = ResponseDTO.builder()
.result((String) resultMap.get("result"))
.data(storeDTO)
.build();
} else if (resultMap.containsKey("dataList")) {
System.out.println("DataList type: " + resultMap.get("dataList").getClass().getName());
List<StoreEntity> storeEntities = (List<StoreEntity>) resultMap.get("dataList");
List<StoreDTO> storeDTOS = new ArrayList<>();
for (StoreEntity storeEntity : storeEntities) {
StoreDTO storeDTO = StoreDTO.builder()
.storeId(storeEntity.getStoreId())
.storeName(storeEntity.getStoreName())
.storeSeller(storeEntity.getStoreSeller())
.storePhone(storeEntity.getStorePhone())
.build();
storeDTOS.add(storeDTO);
}
responseDTO = ResponseDTO.builder()
.result((String) resultMap.get("result"))
.data(storeDTOS)
.build();
} else {
responseDTO = ResponseDTO.builder()
.result((String) resultMap.get("result"))
.data(null)
.build();
}
return responseDTO;
}
@Override
public SimpleResponseDTO toSimpleResponseDTO(@NotNull Map<String, Object> resultMap) {
SimpleResponseDTO simpleResponseDTO;
simpleResponseDTO = SimpleResponseDTO.builder()
.result((String) resultMap.get("result"))
.build();
return simpleResponseDTO;
}
}
package com.wara.store.Controller;
import com.wara.store.Service.StoreService;
import com.wara.store.DTO.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/store")
public class StoreController {
private final StoreService storeService;
private final static Logger logger = LoggerFactory.getLogger(StoreController.class);
public StoreController(@Autowired StoreService storeService) {
this.storeService = storeService;
}
//exist
@GetMapping(value = "/exist/id/{storeId}")
public ResponseEntity<SimpleResponseDTO> existStoreById(@PathVariable("storeId") Long storeId) {
logger.info("[Request] : ExistStoreById");
logger.info("[Data]: " + storeId);
SimpleResponseDTO response = storeService.existStoreById(storeId);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
@GetMapping(value = "/exist/seller/{storeSeller}")
public ResponseEntity<SimpleResponseDTO> existStoreBySeller(@PathVariable("storeSeller") String storeSeller) {
logger.info("[Request] : ExistStoreBySeller");
logger.info("[Data]: " + storeSeller);
SimpleResponseDTO response = storeService.existStoreBySeller(storeSeller);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
//create
@PostMapping(value = "/create", consumes = "application/json")
public ResponseEntity<SimpleResponseDTO> createStore(@RequestBody StoreDTO storeDTO) {
logger.info("[Request] : CreateStore(No Image)");
logger.info("[Data]: " + storeDTO.toString());
SimpleResponseDTO response = storeService.createStore(storeDTO);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(201).body(response);
}
return ResponseEntity.status(400).body(null);
}
//read
@GetMapping(value = "/read/id/{storeId}")
public ResponseEntity<ResponseDTO> readStoreById(@PathVariable("storeId") Long storeId) {
logger.info("[Request] : ReadStoreById");
logger.info("[Data]: " + storeId);
ResponseDTO response = storeService.readStoreById(storeId);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
@GetMapping(value = "/read/seller/{storeSeller}")
public ResponseEntity<ResponseDTO> readStoreBySeller(@PathVariable("storeSeller") String storeSeller) {
logger.info("[Request] : ReadStoreBySeller");
logger.info("[Data]: " + storeSeller);
ResponseDTO response = storeService.readStoreBySeller(storeSeller);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
//update
@PutMapping(value = "/update/id", consumes = "application/json")
public ResponseEntity<SimpleResponseDTO> updateStoreById(@RequestBody StoreDTO storeDTO) {
logger.info("[Request] : UpdateStoreById(No Image)");
logger.info("[Data]: " + storeDTO.toString());
SimpleResponseDTO response = storeService.updateStoreById(storeDTO);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
//delete
@DeleteMapping(value = "/delete/id/{storeId}")
public ResponseEntity<SimpleResponseDTO> deleteStore(@PathVariable("storeId") Long storeId) {
logger.info("[Request] : DeleteStoreById");
logger.info("[Data]: " + storeId);
SimpleResponseDTO response = storeService.deleteStore(storeId);
logger.info("[Response] : " + response.toString());
if(response.getResult().equals("success")){
return ResponseEntity.status(200).body(response);
}
return ResponseEntity.status(400).body(null);
}
}

PostMan을 통해서 위와 같은 요청을 보낼 수 있고, 아래와 같이 데이터베이스에 잘 반영되는 것을 확인할 수 있다.

테스트하고자하는 클래스를 선택하고 ctrl + shift + T

테스트하고자하는 Member 선택하고, OK버튼 클릭시 Test파일이 생성된다.