[MyBatis] INSERT 성공 후 생성된 자원의 PK 같이 얻어오기
zl존석동
·2022. 2. 26. 22:55
쿼리 매퍼인 MyBatis에서도 자원을 생성하면서 동시에 그 정보(Primary Key)를 객체에 얻어와보자
Servlet + Mybatis + Jsp 를 사용하여 웹 서비스를 만들어볼때는 몰랐는데
Spring + MyBatis로 REST API를 만들려다보니까 Mybatis를 사용해 특정 테이블에 자원을 INSERT 하고
즉시 그 자원에 대한 정보를 가져와야 하는 상황이 발생하게 되었다.
기본적으로 Mybatis 를 통한 CUD 쿼리의 작업 결과는 정수로 결과의 성공여부를 나타내주는 것 같았다.
JPA에서는 객체에다가 영속화해줘서 고민해볼 필요가 없는 문제인데 조회 쿼리를 한번 더 날리고 싶지는 않았고
검색하여 본 옛 선배님들의 글들 통해 이를 적용해보았던 내용들을 기록해보았다.
문제 상황: 회원가입 API
@PostMapping
public ResponseEntity<ResponseDTO> signUp(
@Validated(ValidationSequence.class)
@RequestBody SignUpRequest signUpRequest) {
Long memberId = memberService.signUp(signUpRequest);
return ResponseEntity.created(URI.create("/members/" + memberId))
.body(ResponseDTO.builder()
.status(HttpStatus.CREATED).build());
}
회원가입의 경우 리소스가 생성되었기 때문에 201 CREATED 를 응답해주고 싶었고
규칙에 맞게 Location 헤더에 어떤 자원이 생성되었는지를 명시해주고 싶었다.
이런 규칙을 지키려다보니 Member 의 ID(PK) 가 필요하게 되었던 것이다.
회원 뿐만 아니라 모든 자원들의 POST 에 대해 ID 를 헤더에 리턴해줘야 할 것이기 때문에 가볍게 넘어갈 수 없는 문제였다.
사실 REST API 라서 발생한 문제인 것 처럼 적어버렸지만 좀 더 현실적인 예시가 더 많을 것 같다.
회원이 생성될 때 기본적으로 회원이 가지는 생성되거나 수정되어야 하는 또 다른 자원이 있다던가 하는 등의 상황이 많을 것 같았다.
문제 해결: 매퍼 수정하기
<insert id="signUp" parameterType="Member">
insert into member (email, nickname, password)
values (#{email}, #{nickname}, #{password})
<selectKey keyProperty="memberId" order="AFTER" resultType="long">
select member_seq.currval as member_id from dual
</selectKey>
</insert>
selectkey가 쿼리를 통한 작업 전,후에 특정한 키 값을 가져와서 처리할 수 있게끔 해준다.
오라클을 사용했기 때문에 INSERT 작업 후 자동으로 증가하는 PK에 대해 시퀀스로부터 가져올 수 있도록 해주었다.
public Long signUp(Member member) {
session.insert("mapper.MemberMapper.signUp", member);
return member.getMemberId();
}
MemberDAO 클래스에서 DTO 객체에 현재 생성된 자원의 아이디를 얻어올 수 있다.
쿼리를 직접 비교해보진 않았지만 당연히 INSERT 후 SELECT 하는 것 보다는 훨씬 효율적일 것이다.
@Override
public Long signUp(SignUpRequest signUpRequest) {
validDuplicateEmail(signUpRequest.getEmail());
validDuplicateNickname(signUpRequest.getNickname());
return memberDAO.signUp(signUpRequest.toEntity());
}
Service 클래스에서 이렇게 INSERT 결과를 리턴해주면 맨 위에 있던 컨트롤러 API에서 의도한 응답을 잘 해줄 수 있게 된다.
검색해보았을 때 다른 여러 방법들이 더 있었던 것 같지만
오라클이고 시퀀스를 이미 만들었고 자동 증가 트리거도 적용해두었고 이를 활용하는 상황이기 때문에 위 방법이 가장 직관적이고 적절해보여서 사용했던 것 같다!
References
Mybatis, insert in Oracle with sequence id
I have tried with this: <insert id="insertPersonalizacionUsuario" useGeneratedKeys="true" keyProperty="param1.id" keyColumn="id"> INSERT INTO dsk_prop_personali (idpersonalizacion, idusu...
stackoverflow.com
'Java' 카테고리의 다른 글
| Annotation (0) | 2022.02.20 |
|---|---|
| [java] Reflection (0) | 2022.02.14 |
| [Java] ConcurrentModificationException 해결하기 (0) | 2022.02.04 |
| [Java] 올바른 Map Iteration (0) | 2022.01.23 |
| [Java] 예외란 뭘까 (0) | 2022.01.10 |