-
PK가 없는 테이블을 JPA 엔티티로 만들기JAVA/Spring 2021. 12. 7. 10:05반응형
문제의 시작
Spring batch
의 메타테이블 중batch_job_execution_params
의 데이터를 JPA로 조회할 일이 생겼다.
테이블 스키마는 아래와 같았다.CREATE TABLE `batch_job_execution_params` ( `JOB_EXECUTION_ID` bigint(20) NOT NULL, `TYPE_CD` varchar(6) NOT NULL, `KEY_NAME` varchar(100) NOT NULL, `STRING_VAL` varchar(250) DEFAULT NULL, `DATE_VAL` datetime DEFAULT NULL, `LONG_VAL` bigint(20) DEFAULT NULL, `DOUBLE_VAL` double DEFAULT NULL, `IDENTIFYING` char(1) NOT NULL, KEY `JOB_EXEC_PARAMS_FK` (`JOB_EXECUTION_ID`), CONSTRAINT `JOB_EXEC_PARAMS_FK` FOREIGN KEY (`JOB_EXECUTION_ID`) REFERENCES `batch_job_execution` (`JOB_EXECUTION_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
JPA
에 대한 지식이 별로 없어서
PK가 없어도job_execution_id
를@Id
로 선언하면 되지 않을까...? 라고 생각했다...문제의 직면...
BatchJobExecutionParams
엔티티를 아래와 같이 만들었다.@Getter @Entity @Table(name = "BATCH_JOB_EXECUTION_PARAMS") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BatchJobExecutionParams { @Id @Column(name = "JOB_EXECUTION_ID", nullable = false) private Long jobExecutionId; @Column(name = "TYPE_CD", columnDefinition = "VARCHAR(6)", nullable = false) private String typeCd; @Column(name = "KEY_NAME", columnDefinition = "VARCHAR(100)", nullable = false) private String keyName; @Column(name = "STRING_VAL", columnDefinition = "VARCHAR(250)") private String stringVal; @Column(name = "DATE_VAL") private LocalDateTime dateVal; @Column(name = "LONG_VAL") private Long longVal; @Column(name = "DOUBLE_VAL") private Double doubleVal; @Column(name = "IDENTIFYING", columnDefinition = "CHAR(1)", nullable = false) private String identifying; }
오...
QueryDSL
을 붙여서jobExecutionId
로 조회하도록 코드를 짜서 돌려봤다.public List<BatchJobExecutionParams> findExecutionParamsById(Long id) { return queryFactory .select(batchJobExecutionParams) .from(batchJobExecutionParams) .where(batchJobExecutionParams.jobExecutionId.eq(id)) .fetch(); }
DB에 조회해 봤을땐 총 7개의
row
가 조회되었는데
프로그램을 돌리니... 7개는 맞는데... 전부 똑같은row
가 조회되었다...해결 과정
batch_job_execution
테이블도 엔티티로 만들고,QueryDSL
을 붙여서jobExecutionId
로 조회를 해봤는데
DB에서 직접 조회할때랑 동일하게 결과가 잘 나왔다.도대체 뭐가 문제일까...?
그래서
batch_job_execution
테이블과batch_job_execution_params
테이블을 비교해 보았더니
후자에는PK
가 없었다.에이 설마...
폭풍검색!
그 결과 아래와 같은 내용을 찾을 수 있었다.
Every JPA entity must have a primary key.
You can specify a primary key as a single primitive, or JDK object type entity field (see "Configuring a JPA Entity Simple Primary Key Field").
You can specify a composite primary key made up of one or more primitive, or JDK object types using a separate composite primary key class (see "Configuring a JPA Entity Composite Primary Key Class").
You can either assign primary key values yourself, or you can associate a primary key field with a primary key value generator (see "Configuring JPA Entity Automatic Primary Key Generation").If your object does not have an id, but its table does, this is fine. Make the object an Embeddable object, embeddable objects do not have ids. You will need a Entity that contains this Embeddable to persist and query it.
문제 해결!
먼저 만들었던
BatchJobExecutionParams
엔티티에서@Id
어노테이션을 제거한 뒤,jobExecutionId
,typeCd
,keyName
세 개의 컬럼을 복합키로 만들기 위해
얘네를 따로 추출해서BatchJobExecutionParamsId
란 클래스를 만들었다.@Getter @Setter @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BatchJobExecutionParamsId implements Serializable { @Column(name = "JOB_EXECUTION_ID", nullable = false) private Long jobExecutionId; @Column(name = "TYPE_CD", columnDefinition = "VARCHAR(6)", nullable = false) private String typeCd; @Column(name = "KEY_NAME", columnDefinition = "VARCHAR(100)", nullable = false) private String keyName; }
그리고 난 뒤에
BatchJobExecutionParams
엔티티에서BatchJobExecutionParamsId
클래스를 속성으로 추가한 뒤,@EmbeddedId
어노테이션을 추가했다.@Getter @Entity @Table(name = "BATCH_JOB_EXECUTION_PARAMS") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BatchJobExecutionParams { @EmbeddedId private BatchJobExecutionParamsId id; @Column(name = "STRING_VAL", columnDefinition = "VARCHAR(250)") private String stringVal; @Column(name = "DATE_VAL") private LocalDateTime dateVal; @Column(name = "LONG_VAL") private Long longVal; @Column(name = "DOUBLE_VAL") private Double doubleVal; @Column(name = "IDENTIFYING", columnDefinition = "CHAR(1)", nullable = false) private String identifying; }
짜잔!
프로그램을 돌려보니 7개의row
가 모두 다르게 정상적으로 확인이 되었다.@Embeddable
과@EmbeddedId
에 대한 자세한 내용은 여기를 참고하기 바란다.반응형'JAVA > Spring' 카테고리의 다른 글
Factory Pattern within Spring (0) 2020.07.18