고객이 등록되고 나면 고객이 보이스피싱 피해자인지 아닌지를 예측한다.
그리고 예측에 사용되는 요소들을 DB에 저장해야하는데
관련 테이블이 판단결과(RESULT)테이블이다.
원래는 primary key인 id가 CUSTOMER(고객) 테이블의 customerId였는데 프론트에서 이 값을 계속 갖고 있어서 굳이 foreigner key로 할 필요가 없다고 생각해 OneToOne Mapping 부분은 제외하였다!
그러다보니 그냥 CUSTOMER 고객 등록 api와 거의 유사하다!
먼저 entity 클래스를 만들자!
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter// 클래스내 getter 메소드 자동생성
@NoArgsConstructor //기본 생성자 자동추가
@Entity
public class Result { //판단 결과 저장 엔티티
@Id
private Long customerId; //foreigner 키 지정할지, 프론트에서 갖고 있다가 같이 줄지
@Column
private Long withdraw; //만원단위
@Column(nullable = true)
private boolean phone;
@Column(nullable = true)
private boolean victim;
@Builder
public Result( Long customerId, Long withdraw, boolean phone, boolean victim){
this.customerId = customerId;
this.withdraw = withdraw;
this.phone = phone;
this.victim = victim;
}
}
📌 boolean(원시타입) vs Boolean(참조타입)
처음에 휴대전화 탐지 여부를 저장하는 phone과
최종 피해자로 예측되어 알람이 발생했는지의 여부를 저장하는 victim의 변수명을
각각 isPhone, isAlert으로 선언했었다!
그러니까 데이터 저장이 잘 안됨...
이유를 찾아보니
primitive boolean 타입의 변수명이 is 로 사작하면, 실제 변환 시 is 가 생략되기 때문이라고 한다...!
그래서 그냥 변수명을 바꿀지, Boolean으로 바꿀지 고민했다.
사실은 고객테이블의 endTime처럼 isPhone과 isAlert(phone, victim) 역시 ai 연산 후 수정되는 값이기 때문이다.
그래서 맨 처음 등록할 때는 null값으로 넣을 예정이었는데
✅ 널값은 Boolean에만 넣을 수 있다!
그치만 참조타입(Boolean)은 차지하는 메모리양이 원시타입에 비해 훨씬 더 크고,
원시타입을 사용하면 Unboxing 과정을 거치지 않아도 되기 때문에 속도도 빠르다고 해 그냥 변수명을 바꿨다.
초기화는 무조건 false로 하는걸로~
사실 boolean이 차지하는 메모리가 워낙 작다보니 별 차이 없겠지만ㅋㅅㅋ
컨트롤러 작성해주고~
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import pebite.Ponitor_BE.dto.ResultSaveRequestDto;
import pebite.Ponitor_BE.service.ResultService;
@RequiredArgsConstructor
@RestController
public class ResultApiController {
private final ResultService resultService;
@PostMapping("/users/{username}/cost")
public Long save(@RequestBody ResultSaveRequestDto requestDto){
return resultService.save(requestDto);
}
}
다음과 같이 서비스도 작성해주고!
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pebite.Ponitor_BE.dto.ResultSaveRequestDto;
import pebite.Ponitor_BE.repository.ResultRepository;
@RequiredArgsConstructor
@Service
public class ResultService {
private final ResultRepository resultRepository;
@Transactional
public Long save(ResultSaveRequestDto requestDto){
return resultRepository.save(requestDto.toEntity()).getCustomerId();
}
}
레포지토리도 다음과 같이 작성해준다.
import org.springframework.data.jpa.repository.JpaRepository;
import pebite.Ponitor_BE.model.Result;
public interface ResultRepository extends JpaRepository<Result, Long> {
}
Dro부분을 아래와 같이 작성해주면 끝!
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import pebite.Ponitor_BE.model.Result;
@Getter
@NoArgsConstructor//기본 생성자 생성
public class ResultSaveRequestDto {
private Long customerId;
private Long withdraw;
private boolean phone;
private boolean victim;
@Builder
public ResultSaveRequestDto(Long customerId, Long withdraw, boolean phone, boolean victim){
this.customerId = customerId;
this.withdraw = withdraw;
this.phone = phone;
this.victim = victim;
}
public Result toEntity(){
return Result.builder()
.customerId(customerId)
.withdraw(withdraw)
.phone(phone)
.victim(victim)
.build();
}
}
포스트맨으로 데이터를 날려보면
아래와 같이 잘 저장되고 있음을 확인할 수 있당!