JPA 복합키 생성

정명진·2022년 6월 8일
0
post-thumbnail

JPA도 복합키(Composite Key)가 가능할까?

PlayStore에서 자사 앱 제품들에 대해 Selenium을 이용하여 앱 정보들을 크롤링후 DB에 저장하는 프로그램을 개발하던중 복합키가 필요하게 되었다.

기존 강의에서는 단일키를 Primary Key로 설정해서 복합키 생성은 처음이었다. 하지만 막상 해보니 이해는 잘 갔다. 역시 짬을 내서 따로 더 공부를 해야겠다...

아래는 앱 버전을 따로 관리하는 VersionInfo Entity다. 잘 살펴보면 @EmbeddedId 어노테이션이 처리된 칼럼이 있다. @EmbeddedId는 @Embeddable 처리된 VersionId를 Primary Key로 갖게 해주는 기능을 한다. 즉 VersionId에 존재하는 칼럼들을 Primary Key로 갖게 해주는 것 이다. 따라서 appName, version을 Primary Key로 갖는 Entity가 되는 것 이다.


@Entity
@Getter
public class VersionInfo implements Serializable {


    @EmbeddedId
    private VersionId versionId;

    @Column(name = "UpdatedDate")
    private String updatedDate;

    private LocalDateTime createdDate;
    private LocalDateTime modifiedDate;

    public void setCreatedDate(){
        LocalDateTime now = LocalDateTime.now();
        createdDate = now;
        modifiedDate = now;
    }

    public VersionInfo() {
    }

    public VersionInfo(VersionId versionId, String updatedDate) {
        this.versionId = versionId;
        this.updatedDate = updatedDate;
    }
}


@Embeddable
@Getter
@Setter
public class VersionId implements Serializable {
    private String appName;
    private String version;

    public VersionId(String appName, String version) {
        this.appName = appName;
        this.version = version;
    }

    public VersionId() {
    }
}

실제로 잘 작동하는지 확인을 위해 해당 테스트를 2번 실행해봤다.

@Test
@Transactional
@Rollback(value = false)
public void versionTest(){
        String[] arr = {"com.shinhan.sbanking", "com.shinhan.smartcaremgr", "com.shinhan.sbankmini"};

        List<HashMap<String, String>> listInfos = crawler.getInfoList(arr);
        for (HashMap<String, String> infos : listInfos) {
            System.out.println("===========================\n");

            String appName = infos.get("앱 이름");
            String version = infos.get("버전");
            String updatedDate = infos.get("업데이트 날짜");
            updatedDate = updatedDate.replaceAll(" ","");
            updatedDate = updatedDate.substring(0, updatedDate.length()-1);
            VersionId versionId = new VersionId(appName, version);
            versionInfoRepository.save(new VersionInfo(versionId, updatedDate));
            System.out.println("===========================\n");
     }
}

그랬더니 아래와 같은 에러가 나오며 테스트가 종료되었다.

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUBLIC.PRIMARY_KEY_8 ON PUBLIC.VERSION_INFO(APP_NAME, VERSION) VALUES 1"; SQL statement:
insert into version_info (created_date, modified_date, updated_date, app_name, version) values (?, ?, ?, ?, ?) [23505-212]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

즉 중복된 키로 인해 DB에 insert를 할 수 없다는 것이다. 정상 작동을 확인 할 수 있었다..!

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..

0개의 댓글