예제를 만들자 뚱땅뚱땅

API 만들기 연습 #10

NEWDODORIPYO 2022. 9. 5. 09:09

삭제 기능 만들기

삭제 기능

삭제 기능을 구현하기 전 가장 고민했던 부분은 바로 insert 기능을 만들 때 api <고객> 테이블에 Count 되는 부분이었다 추가할 때 Count 값이 증가한다면 삭제할 때는 감소해야 하는데 처음에는 그냥 반대로 +1 이 아닌 -1 하면 되는 거 아닌가? 하고 진행했지만 insert 할 때는 입력창에 입력하는 api <고객>의 PK값이 있는데 삭제할 때는 그게 없으니 api <고객> 테이블에 Count를 찾을 수가 없었다

고민한 3가지 방법

1. 삭제할 때 insert처럼 고객 PK를 입력받기 <쉽게 해결하는 수단이지만… 이건 말이 안 된다>

2. 장치에 상태를 만들어 삭제가 아닌 상태를 변경하는 방향 <DB에 데이터가 계속 쌓이는 문제가 있다 실질적인 삭제가 아니기 때문에>

3. 삭제할 때 고객의 PK를 얻어온다 … < 가장 원하는 방법인데 좀처럼 방법이 생각이 안 남>

이걸 어떻게 처리할까를 한참을 고민하고 지금의 코드를 작성했습니다.

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을 검사

}

  • 삭제 기능의 deviceDelete
  • Count 값의 변화를 위해 테이블을 한번 조회하는 getPk

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">


    <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>
   
</mapper>
  • getPk는 삭제할 때 유효성 검사와 apiRepository.deletDevicesCount 에서 memberNumber을 매칭 할 때 이용된다 (apiRepository.deletDevicesCount 는 아래에서 설계할 예정)

ApiRepository

package com.apiservice.repository;

import com.apiservice.model.ApiDTO;
import com.apiservice.model.ApiVO;
import com.apiservice.model.ListDTO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ApiRepository {

    void insert(ApiDTO apiDTO);

    void update(ApiDTO apiDTO);

    void delete(Integer memberNumber);

    List<ApiVO>selectList(ListDTO listDTO);

    int getTotal(ListDTO listDTO);

    ApiVO getPk(ApiDTO apiDTO); // api 테이블 pk

    ApiVO getId(ApiDTO apiDTO); // api 테이블 memberId

    void updateDevicesCount(@Param("memberNumber") Integer memberNumber, @Param("amount") int amount);

    void deleteDevicesCount(@Param("memberNumber") Integer memberNumber);

}
  • deleteDevicesCount는 device 삭제를 할때 Count 값의 감소를 위한 코드

ApiRepository.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.ApiRepository">

    <sql id="search">
        <where>
            <if test="keyword != null">
                <foreach collection="types" item="item" separator="OR" open="(" close=")">
                    <if test = 'item == "i"'>
                        member_id like concat('%',#{keyword} , '%')
                    </if>
                    <if test='item =="n"'>
                        member_name like concat('%' , #{keyword} , '%')
                    </if>
                    <if test='item =="p"'>
                        member_phone like concat('%' , #{keyword} , '%')
                    </if>
                    <if test='item =="a"'>
                        advert like concat('%' , #{keyword} , '%')
                    </if>
                </foreach>
            </if>
        </where>

    </sql>

    <insert id="insert">
        insert into api.api(member_id , member_pw , member_name , member_phone , advert)
        values (#{memberId} , #{memberPw} , #{memberName} , #{memberPhone} , #{advert})
    </insert>


    <update id="update">
        update api.api
        set update_date  = now()
          <if test=" memberId != null and memberId != '' ">
          , member_id    = #{memberId}
          </if>
          <if test="memberPw != null and memberPw != '' ">
          , member_pw    = #{memberPw}
          </if>
          <if test="memberName != null and memberName != '' ">
          , member_name  = #{memberName}
          </if>
          <if test="memberPhone != null and memberPhone != '' ">
          , member_phone = #{memberPhone}
          </if>
          <if test="advert != null and advert != '' ">
          , advert       = #{advert}
          </if>
        where member_number = #{memberNumber}
    </update>

    <delete id="delete">
        delete
        from api.api
        where member_number = #{memberNumber}
    </delete>

    <select id="selectList" resultType="com.apiservice.model.ApiVO">
        select member_number ,member_id , member_pw , member_name , member_phone , advert , update_date
        from api.api
        <include refid="search"></include>
        order by member_number desc
        limit #{skip},#{size}
    </select>

    <select id="getTotal" resultType="int">
        select count (member_number) from api.api
        <include refid="search"></include>
    </select>

    <select id="getPk" resultType="com.apiservice.model.ApiVO">
        select member_number from api.api
        where member_number = #{memberNumber}
    </select>

    <select id="getId" resultType="com.apiservice.model.ApiVO">
        select member_id  from api.api
        where member_id = #{memberId}
    </select>

    <update id="updateDevicesCount">
        update api.api set deviceCount = deviceCount + #{amount} where member_number = #{memberNumber}
    </update>


    <update id="deleteDevicesCount">
        update api.api set deviceCount = deviceCount - 1 where member_number = #{memberNumber}
    </update>
</mapper>
  • deleteDevicesCount 는 쿼리가 실행될 때 Count 값에 -1을 해주고 memberNumber로 맵핑한다

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);
}
  • Transactional 어노테이션을 걸어주자

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());

    }
}

⭐가장 고민을 많이 한 부분이다 우선 getPK로 service_number , member_number 두 개를 확인하고 유효성 검사를 먼저 진행해준다 그리고 이제 삭제 로직이 실행되고 이후 api <고객> 테이블의 Count 값의 감소를 위한 apiRepository.deleteDevicesCount 가 실행된다 이때 맵핑하는 memberNumber을 getPk에서 받아온다 이렇게 하면 삭제되는 서비스가 어떤 고객에게 등록된 서비스인지 확인이 가능해진다.

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 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);
    }
}
  • register 쪽 서비스 코드는 다음에 리뷰 하겠습니다!!

테스트를 해보자

현재 device <장치> 테이블

현재 api <고객> 테이블

10번 고객에게 1개의 장치가 등록되어있다 이걸 지워보자

swagger-ui 테스트

  • 23번으로 등록된 장치를 삭제했다

삭제 후 device <장치> 테이블

삭제 후 api <고객> 테이블

계획한 대로 로직이 잘 동작하고 있는 걸 확인할 수 있다

'예제를 만들자 뚱땅뚱땅' 카테고리의 다른 글

API 만들기 연습 #11  (1) 2022.09.06
API 만들기 연습 #9  (0) 2022.09.02
API 만들기 연습 #8 추가 설계  (0) 2022.09.01
API 만들기 연습 #7 검색  (0) 2022.08.31
API 만들기 연습 #6 유효성 검증  (0) 2022.08.30