조회 & 검색 그리고 유효성 검사
DeviceRepository
package com.apiservice.repository;
import com.apiservice.model.DeviceDTO;
import com.apiservice.model.DeviceVO;
import com.apiservice.model.ListDTO;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface DeviceRepository {
void deviceInsert(DeviceVO deviceVO);
void deviceDelete(Integer serviceNumber);
DeviceVO getPk(DeviceDTO deviceDTO); // device 테이블의 pk 와 member_number을 검사
List<DeviceVO> selectList(ListDTO listDTO);
int getTotal(ListDTO listDTO);
}
- 조회 기능을 하는 selectList
- Total 값을 가져오는 getTotal
DeviceRepository.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.apiservice.repository.DeviceRepository">
<sql id="search">
<where>
<if test="keyword != null">
<foreach collection="types" item="item" separator="OR" open="(" close=")">
<if test = 'item == "n"'>
device_name like concat('%',#{keyword} , '%')
</if>
<if test='item =="t"'>
device_type like concat('%' , #{keyword} , '%')
</if>
<if test='item =="p"'>
member_number like concat('%' , #{keyword} , '%')
</if>
<if test='item =="r"'>
region like concat('%' , #{keyword} , '%')
</if>
</foreach>
</if>
</where>
</sql>
<insert id="deviceInsert">
insert into api.device( device_name, device_type, installer, in_date, region, member_number)
value(#{deviceName},#{deviceType},#{installer},now(),#{region},#{memberNumber})
</insert>
<delete id="deviceDelete">
delete
from api.device
where service_number = #{serviceNumber}
</delete>
<select id="getPk" resultType="com.apiservice.model.DeviceVO">
select service_number , member_number from api.device
where service_number = #{serviceNumber}
</select>
<select id="selectList" resultType="com.apiservice.model.DeviceVO">
select service_number, device_name, device_type, installer, in_date, region, member_number
from api.device
<include refid="search"></include>
order by service_number desc
limit #{skip},#{size}
</select>
<select id="getTotal" resultType="int">
select count (service_number) from api.device
<include refid="search"></include>
</select>
</mapper>
- 검색 기능과 조회 쿼리는 기존 코드와 동일합니다
DeviceService
package com.apiservice.service;
import com.apiservice.model.*;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public interface DeviceService {
void register(DeviceDTO deviceDTO , ApiDTO apiDTO);
void delete(Integer serviceNumber , DeviceDTO deviceDTO);
ListResponseDTO<DeviceDTO> getList(ListDTO listDTO);
}
DeviceServiceImpl
package com.apiservice.service;
import com.apiservice.controller.Handler.CustomException;
import com.apiservice.model.*;
import com.apiservice.model.Error.ErrorCode;
import com.apiservice.repository.ApiRepository;
import com.apiservice.repository.DeviceRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Log4j2
@RequiredArgsConstructor
public class DeviceServiceImpl implements DeviceService{
private final ApiRepository apiRepository;
private final DeviceRepository deviceRepository;
private final ModelMapper modelMapper;
@Override
public void register(DeviceDTO deviceDTO , ApiDTO apiDTO) {
DeviceVO deviceVO = modelMapper.map(deviceDTO, DeviceVO.class);
deviceRepository.deviceInsert(deviceVO);
//api<고객> 테이블 에 존재하는 PK 인지 확인
if(apiRepository.getPk(apiDTO) ==null){
log.info("ErrorCode NOT_INFO");
throw new CustomException(ErrorCode.NOT_INFO);
}
apiRepository.updateDevicesCount(deviceDTO.getMemberNumber(),1);
}
@Override
public void delete(Integer serviceNumber , DeviceDTO deviceDTO) {
//유효성 검사와 member_number을 매칭하기 위한 select
DeviceVO getPk = deviceRepository.getPk(deviceDTO);
//존재 안 하는 장치는 삭제할 수 없다
if(getPk == null){
throw new CustomException(ErrorCode.NOT_INFO);
}
log.info("deviceDelete");
deviceRepository.deviceDelete(serviceNumber);
apiRepository.deleteDevicesCount(getPk.getMemberNumber());
}
@Override
public ListResponseDTO<DeviceDTO> getList(ListDTO listDTO) {
List<DeviceVO> apiList = deviceRepository.selectList(listDTO);
//deviceVO 를 DeviceDTO 타입의 객체로 맵핑
List<DeviceDTO> dtoList =
apiList.stream().map(deviceVO -> modelMapper.map(deviceVO,DeviceDTO.class))
.collect(Collectors.toList());
return ListResponseDTO.<DeviceDTO>builder()
.dtoList(dtoList)
.total(deviceRepository.getTotal(listDTO))
.build();
}
}
이 부분에서 중요한 건 2가지가 있습니다
우선 첫번째는 당연히 조회하는 쪽 로직 이 로직은 전에 만들었던 로직과 똑같습니다 중요하다기보다는 목표인 코드이죠 그럼 다른 한 가지는 무엇이냐?
두 번째 바로 insert 쪽 유효성 검사입니다
장치를 등록할 때 존재 안 하는 고객에게는 장치를 등록할 수 없습니다 그렇기 때문에 먼저 고객이 존재하는지부터 알아야 합니다 그래서
//api<고객> 테이블 에 존재하는 PK 인지 확인
if(apiRepository.getPk(apiDTO) ==null){
log.info("ErrorCode NOT_INFO");
throw new CustomException(ErrorCode.NOT_INFO);
}
이렇게 확인해주고 없다면 예외를 던지고 있습니다 이 코드를 위해 register에 매개변수로 ApiDTO를 받은 것이죠 apiDTO가 없다면 위 코드를 돌릴 수 없기 때문이죠 하지만 Controller에서는 매개변수로 받으면 어지러워진다….
DeviceController
package com.apiservice.controller;
import com.apiservice.model.ApiDTO;
import com.apiservice.model.DeviceDTO;
import com.apiservice.model.ListDTO;
import com.apiservice.model.ListResponseDTO;
import com.apiservice.service.DeviceService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/device/")
@Log4j2
@RequiredArgsConstructor
public class DeviceController {
private final DeviceService deviceService;
@ApiOperation("device Get list")
@GetMapping("/list")
public ListResponseDTO<DeviceDTO> list(ListDTO listDTO){
log.info("Api list");
log.info(listDTO);
ListResponseDTO<DeviceDTO> responseDTO = deviceService.getList(listDTO);
log.info("List Controller ");
log.info(responseDTO);
return responseDTO;
}
@ApiOperation("Device Post register")
@PostMapping("/register")
public ResponseEntity registerPost(DeviceDTO deviceDTO){
log.info(deviceDTO);
log.info("controller register");
deviceService.register(deviceDTO , ApiDTO.builder()
.memberNumber(deviceDTO.getMemberNumber())
.build());
return new ResponseEntity(HttpStatus.OK);
}
@ApiOperation("Device post delete")
@PostMapping("/delete/{serviceNumber}")
public ResponseEntity delete(@PathVariable("serviceNumber") Integer serviceNumber , DeviceDTO deviceDTO){
log.info("-----------------------");
log.info("delete");
log.info("------------------");
deviceService.delete(serviceNumber , deviceDTO);
return new ResponseEntity(HttpStatus.OK);
}
}
- register에서는 매개변수로는 ApiDTO를 받게 되면 입력창에 api의 목록까지 전부 보인다 그렇기 매개변수로는 daviceDTO 만 받아주면 됩니다
- service 코드를 실행할 때 member 받아줍니다
조회 같은 경우는 기존 코드와 거의 동일하기에 테스트 과정은 건너뛰고 유효성 검사를 위해 이동해보죠 <물론 만들 때는 테스트를 계속 진행하면서 했습니다😉>
DeviceDTO
package com.apiservice.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DeviceDTO {
private Integer serviceNumber; // 서비스 번호
@NotEmpty(message = "장치 넘버를 입력해 주세요")
private String deviceName; // 장치 이름
@Size(max=31)
@NotEmpty(message = "장치 종류를 입력해 주세요")
private String deviceType; // 장치 종류
@NotEmpty(message = "설치 기사 이름을 입력해 주세요")
private String installer; // 설치 기사
@NotEmpty(message = "지역을 입력해 주세요")
private String region; // 지역
private LocalDateTime inDate; // 설치 날짜
private Integer memberNumber; // 고객 번호
}
- memberNumber에 조건을 안 걸어준 이유는 서비스단에서 이미 검사를 하기 때문에 굳이 걸지 않았습니다
- deviceType는 varchar(60) 이기에 문자열의 max 크기를 정해주었습니다
DeviceController
package com.apiservice.controller;
import com.apiservice.model.ApiDTO;
import com.apiservice.model.DeviceDTO;
import com.apiservice.model.ListDTO;
import com.apiservice.model.ListResponseDTO;
import com.apiservice.service.DeviceService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/device/")
@Log4j2
@RequiredArgsConstructor
public class DeviceController {
private final DeviceService deviceService;
@ApiOperation("device Get list")
@GetMapping("/list")
public ListResponseDTO<DeviceDTO> list(ListDTO listDTO){
log.info("Api list");
log.info(listDTO);
ListResponseDTO<DeviceDTO> responseDTO = deviceService.getList(listDTO);
log.info("List Controller ");
log.info(responseDTO);
return responseDTO;
}
@ApiOperation("Device Post register")
@PostMapping("/register")
public ResponseEntity registerPost(@Validated DeviceDTO deviceDTO){
log.info(deviceDTO);
log.info("controller register");
deviceService.register(deviceDTO , ApiDTO.builder()
.memberNumber(deviceDTO.getMemberNumber())
.build());
return new ResponseEntity(HttpStatus.OK);
}
@ApiOperation("Device post delete")
@PostMapping("/delete/{serviceNumber}")
public ResponseEntity delete(@PathVariable("serviceNumber") Integer serviceNumber , DeviceDTO deviceDTO){
log.info("-----------------------");
log.info("delete");
log.info("------------------");
deviceService.delete(serviceNumber , deviceDTO);
return new ResponseEntity(HttpStatus.OK);
}
}
- @Validated 걸어줍니다
여기까지 2차로 설계했던 부분의 코드가 끝났습니다 만들면서 생각지도 못한 문제들이 생겨 고생을 좀 했지만 그래도 어떻게든 만들었네요
기초 설계에서부터 조금 아쉬운 부분들이 있지만 다음에 만들 때는 이런 부분들을 보완해서 만들면 되겠죠?
'예제를 만들자 뚱땅뚱땅' 카테고리의 다른 글
API 만들기 연습 #10 (0) | 2022.09.05 |
---|---|
API 만들기 연습 #9 (0) | 2022.09.02 |
API 만들기 연습 #8 추가 설계 (0) | 2022.09.01 |
API 만들기 연습 #7 검색 (0) | 2022.08.31 |
API 만들기 연습 #6 유효성 검증 (0) | 2022.08.30 |