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