본문 바로가기

카테고리 없음

[아이디어] 데이터베이스 행 삭제 처리 시 UK(Unique Key) 제약조건으로 인한 값 중복 문제 회피하기

728x90

개발을 하다 보면 UK(Unique Key) 제약조건을 이용해야 하는 경우가 빈번하게 발생한다.

 

유저인사이트에서는 데이터를 물리적으로 삭제하는 행위를 delete라 하며, 데이터를 물리적으로 삭제하지 않고 삭제된 것 처럼 보존하는 행위를 remove라 정의하여 활용 중에 있다.

 

겪었던 문제

가장 대표적으로 로그인 기능에 사용되는 사용자 ID(이하 username이라 함)를 예로 들 수 있는데, 만약 사용자가 탈퇴할 때 remove처리를 해야 한다면 이 username을 어떻게 처리해야 할 지 난감한 경우가 생길 수 있다.

(사용자 입장에서는 만약 다시 가입하기를 희망한다면 같은 아이디를 사용할 확률이 매우 높기 때문에..)

 

솔루션

아래는 강의실 정보를 관리하는 테이블에서 UK인 강의실명을 재사용 할 수 있게 처리하는 방법이다.

 

room 테이블을 생성하는 코드

  • name 필드는 UK 제약조건이 걸려있다.
  • removed 가 true가 되면 사용자에게는 삭제된 것과 같이 보이지만 테이블에는 자료가 남아있다.
CREATE TABLE IF NOT EXISTS room (
    id              int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
    name            character varying(60) NOT NULL,
    removed         boolean NOT NULL DEFAULT false,

    CONSTRAINT room_pkey PRIMARY KEY (id),
    CONSTRAINT room_ukey UNIQUE (name)
);

Room 엔티티 구현체

  • 실제로 테이블에 name의 사이즈는 60으로 정의하였다.
    remove처리를 위해 사용자는 최대 50까지밖에 사용할 수 없게 한다.
@Getter
@Setter
@Entity
@Table(name = "room")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Room {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @EqualsAndHashCode.Include
  private Integer id;

  @NotBlank
  @Size(min = 2, max = 50)
  private String name;

  private boolean removed = true;
}

Room을 remove처리하는 코드

  • 삭제할 때 room의 removed 필드는 true로 바꾼다.
  • 삭제되는 room은 고유한 id필드 값을 이용해 절대 중복될 수 없게 처리하며, 향후 식별이 가능하게 기존 값을 남긴다.
@Override
  public long removeById(Integer id) {
    BooleanBuilder builder = new BooleanBuilder();

    builder.and(room.id.eq(id));

    return update(room)
        .set(room.name,
            room.name.concat(Expressions.asString("(삭제)").concat(room.id.stringValue())))
        .set(room.removed, true)
        .execute();
  }

 

 

728x90