일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 무시하기
- jar 소스보기
- 스프링 배치 메타 테이블
- multi update
- JSON 분할
- JSON 분리
- 성능개선
- batchInsert
- 마리아디비
- JobExecutionAlreadyRunningException
- JSONObject 분할
- 스프링 리액티브 프로그래밍
- org.json
- str_to_date
- 스테이지에 올리기
- 스프링 배치 공식문서
- date_format
- Meta Table
- spring reactive programming
- ChainedTransactionManager #분산데이터베이스 #Spring Boot #MyBatis
- 폐기하기
- 문자형을 날짜형으로
- JSON 분해
- nonblocking
- JSONArray 분할
- 마이바티스 트랜잭션
- git stage
- spring webflux
- 스프링 웹플럭스
- 날짜형을 문자형으로
- Today
- Total
ebson
[AI 활용과 개발] ChatGPT를 활용하여 JPA 개발하고 테스트하기 본문
원하는 서비스의 요구사항에 맞추어 기술을 선택하고 이를 활용하기 위해 온라인 강의를 듣고 공식 개발 문서와 관련 개발 서적을 정독하는 방법도 좋겠지만 이미 학습을 마친 동료나 조수가 있다면 그에게 요구사항을 전달하여 템플릿 코드를 얻을 수 있을 것이다. 필자는 Spring Data JPA를 활용하기 위해 먼저 관련 온라인 강의를 수강했다. 그 결과 학습할 양이 많다는 사실을 알게 되었다. 그래서 내가 계획하고 있던 학습량을 수없이 끝내고도 남았을 ChatGPT 에게 도움을 요청하기로 했다.
ChatGPT 에게 JPA 에 대한 질문하기
Spring Data JPA 를 사용하기 위한 기본 질문들을 ChatGPT에게 해보았다. 필수 의존성과 설정 코드, 핵심 원리, 영속성 컨텍스트의 장점을 질문해보았다. 아래는 ChatGPT 의 대답이다.
참고로, 아래와 같이 질문하는 키워드가 명확한 경우에는 키워드만 전달하는 것에 ChatGPT가 더 구체적인 답변을 제공하는 모습이었다.
이상의 내용을 참고하고 개인적으로 공부한 내용들을 적용해 아래와 같이 Spring Data JPA 를 사용하기 위한 코드를 application.properties 파일과 build.gradle.kts 파일에 추가했다.
# JPA configuration
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy = org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# spring.jpa.hibernate.ddl-auto=create
# spring.jpa.hibernate.ddl-auto=create-drop
# spring.jpa.hibernate.ddl-auto=update
# spring.jpa.hibernate.ddl-auto=validate
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
ChatGPT 에게 테이블 생성문을 Prompt로 전달하여 Entity 클래스 작성 요청하기
기본 설정을 마쳤으므로 Spring Data JPA 의 영속성 컨텍스트를 활용하기 위한 Entity 클래스를 작성해야 한다. 이를 위해 데이터베이스에 생성한 테이블의 컬럼 하나하나를 엔티티 클래스의 필드로 옮겨 적을 수 있지만, 정답과 패턴이 있는 작업이었기 때문에 ChatGPT에게 맡겨보았다.
테이블명과 컬럼명의 매핑, 데이터베이스의 자료형과 자바의 자료형 매핑, 연관관계 까지의 번거로운 작업들을 ChatGPT가 단 몇초만에
해주었다. 그리고 아래와 같이 추가 요구사항을 적용하는 것도 가능했다.
다음으로 생성일시와 최근수정일시를 적용하기 위한 어노테이션의 동작방식에 대해서 추가로 질문해보았다.
이상의 생성일시와 최근수정일시 적용을 위한 어노테이션 설명에 대한 ChatGPT의 대답을 정리하면 다음과 같다. @PrePersist 어노테이션은 엔티티가 데이터베이스에 저장되기 전에 실행되며 유효성 검사를 해야하는 경우에 사용할 수 있고 @CreationTumeStamp 어노테이션은 엔티티가 데이터베이스에 저장되는 시점에 현재 일시를 적용한다. 마찬가지로 @PreUpdate 어노테이션은 엔티티가 데이터베이스로 업데이트되기 전에 실행되며 검증 로직을 수행하는 경우에 사용할 수 있고 @UpdateTimestamp 어노테이션은 엔티티가 데이터베이스로 업데이트되는 시점에 현재 일시를 적용한다.
ChatGPT가 제공해준 내용들을 참고하여 MariaDB 으로 생성한 SKILL_RES_V1_VERSION 테이블에 대하여 다음과 같은 SkillResV1VersionEntity 클래스를 작성할 수 있다.
# SKILL_RES_V1_VERSION 테이블 생성문
CREATE TABLE `SKILL_RES_V1_VERSION` (
`VERSION_ID` BINARY(16) NOT NULL DEFAULT UNHEX(REPLACE(UUID(),'-','')),
`BLOCK_ID` VARCHAR(45) NOT NULL,
`BLOCK_CODE` VARCHAR(45) NOT NULL,
`MAJOR` INT NULL,
`MINOR` INT NULL,
`CREATED_DATE` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`LAST_UPDATED_DATE` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`CREATOR` VARCHAR(45) NULL,
`LAST_UPDATER` VARCHAR(45) NULL
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
;
ALTER TABLE `SKILL_RES_V1_VERSION` ADD CONSTRAINT `PK_SKILL_RES_V1_VERSION` PRIMARY KEY (
`VERSION_ID`
);
ALTER TABLE `SKILL_RES_V1_VERSION` ADD CONSTRAINT `FK_VERSION_BLOCK_ID` FOREIGN KEY (
`BLOCK_ID`
)
REFERENCES `BUILDER_V1_BLOCK` (
`BLOCK_ID`
);
// SkillResV1VersionEntity 클래스
@Entity
@Table(name = "SKILL_RES_V1_VERSION")
@Getter @Setter
public class SkillResV1VersionEntity {
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(name = "VERSION_ID", nullable = false, columnDefinition = "BINARY(16)")
@Convert(converter = UUIDToBytesConverter.class)
private UUID versionId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "BLOCK_ID", referencedColumnName = "BLOCK_ID", nullable = false, foreignKey = @ForeignKey(name = "FK_VERSION_BLOCK_ID"))
private BuilderV1BlockEntity builderV1BlockEntity;
@Column(name = "BLOCK_CODE", nullable = false, length = 45)
private String blockCode;
@Column(name = "MAJOR")
private Integer major;
@Column(name = "MINOR")
private Integer minor;
@Column(name = "CREATED_DATE", nullable = false)
@CreationTimestamp
private LocalDateTime createdDate;
@Column(name = "LAST_UPDATED_DATE", nullable = false)
@UpdateTimestamp
private LocalDateTime lastUpdatedDate;
@Column(name = "CREATOR", length = 45)
private String creator;
@Column(name = "LAST_UPDATER", length = 45)
private String lastUpdater;
@PrePersist
protected void onCreate() {
/**
* 저장 전 검증 로직 수행
* LocalDateTime now = LocalDateTime.now();
* this.createdDate = now;
* this.lastUpdatedDate = now;
*/
}
@PreUpdate
protected void onUpdate() {
/**
* 업데이트 전 검증 로직 수행
* this.lastUpdatedDate = LocalDateTime.now();
* */
}
}
BINARY(16) 형의 컬럼을 UUID 필드에 매핑하기 위한 컨버터 클래스 작성하기
한편, SKILL_RES_V1_VERSION 테이블의 VERSION_ID 컬럼의 자료형이 BIMARY(16) 인 이유는 UUID 문자열을 변환하여 저장하는 방식을 선택했기 때문이다. 그래서 엔티티 클래스에서 이를 UUID 자료형으로 저장하려면 컨버터 클래스가 필요하다. JPA 에서는 데이터베이스 컬럼의 자료형과 엔티티 클래스의 자료형 사이의 변환을 위해 AttributeConverter<X,Y> 인터페이스를 다음과 같이 제공한다.
package jakarta.persistence;
/**
* A class that implements this interface can be used to convert
* entity attribute state into database column representation
* and back again.
* Note that the X and Y types may be the same Java type.
*
* @param <X> the type of the entity attribute
* @param <Y> the type of the database column
*/
public interface AttributeConverter<X,Y> {
/**
* Converts the value stored in the entity attribute into the
* data representation to be stored in the database.
*
* @param attribute the entity attribute value to be converted
* @return the converted data to be stored in the database
* column
*/
public Y convertToDatabaseColumn (X attribute);
/**
* Converts the data stored in the database column into the
* value to be stored in the entity attribute.
* Note that it is the responsibility of the converter writer to
* specify the correct <code>dbData</code> type for the corresponding
* column for use by the JDBC driver: i.e., persistence providers are
* not expected to do such type conversion.
*
* @param dbData the data from the database column to be
* converted
* @return the converted value to be stored in the entity
* attribute
*/
public X convertToEntityAttribute (Y dbData);
}
보는 바와 같이 X 자료형에서 Y 자료형으로, Y 자료형을 X 자료형으로 변환하는 메서드 2개를 가지는 간단한 인터페이스이다. 내가 변환하려는 자료형을 적용해 구현체를 작성하고 엔티티 클래스에 등록하면, JPA 에서 변환 작업을 해준다. UUID 자료형과 byte[] 자료형 사이의 변환을 위한 UUIDToBytesConverter 클래스를 다음과 같이 작성할 수 있다.
@Converter(autoApply = true) // 이 컨버터를 자동으로 적용하도록 설정합니다.
public class UUIDToBytesConverter implements AttributeConverter<UUID, byte[]> {
@Override
// UUID 객체를 데이터베이스 컬럼에 저장하기 위해 byte[]로 변환합니다.
public byte[] convertToDatabaseColumn(UUID uuid) {
if (uuid == null) {
return null;
}
long mostSigBits = uuid.getMostSignificantBits();
long leastSigBits = uuid.getLeastSignificantBits();
return ByteBuffer.allocate(16)
.putLong(mostSigBits)
.putLong(leastSigBits)
.array();
}
@Override
// 데이터베이스의 byte[]를 애플리케이션에서 사용하기 위해 UUID 객체로 변환합니다.
public UUID convertToEntityAttribute(byte[] bytes) {
if (bytes == null || bytes.length != 16) {
return null;
}
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
long mostSigBits = byteBuffer.getLong();
long leastSigBits = byteBuffer.getLong();
return new UUID(mostSigBits, leastSigBits);
}
}
JPA 활용 코드 완성하고 테스트 하기
데이터베이스 테이블들을 JPA 를 통해 관리하기 위해서 Entity 클래스를 작성한 후에는 JpaRepository 를 extends 하여 인터페이스에서 제공해주는 메서드를 활용할 수 있다. 아래와 같이 작성하고 테스트해보았다.
@Repository
public interface SkillResV1VersionEntityRepository extends JpaRepository<SkillResV1VersionEntity, UUID> {
}
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class SkillResV1VersionEntityRepositoryTest {
@Autowired
private SkillResV1VersionEntityRepository repository;
... 생략
@Test
public void getReferenceByIdTest(){
UUID versionId = UUID.fromString(UUIDFormatter.formatToUUID("EC26D695038D11EFB5380A48BC1A5EE1"));
SkillResV1VersionEntity entity = repository.getReferenceById(versionId);
Assertions.assertNotNull(entity);
Assertions.assertEquals(entity.getBlockCode(), "FP_S01_B01");
}
... 생략
}
ChatGPT 를 활용한 JPA 개발 후기
이상과 같이 ChatGPT 를 활용해 JPA 으로 데이터베이스 테이블들을 관리하기 위한 코드를 작성하고 테스트 해보았다. 테이블 컬럼을 JPA Entity 클래스의 필드로 옮기는 작업 중 번거로운 작업을 ChatGPT 가 보다 빠르고 정확하게 대신 작업해준다는 것 외에도 궁금한 점이 있으면 키워드 만으로도 실시간으로 정제된 대답을 얻을 수 있는 점이 개발과정의 비효율성을 개선함과 동시에 집중도 향상에도 도움이 되는 것 같다.
시중에 정형화된 패턴이 있는 코드들의 자동 생성을 돕는 솔루션들이 많은 것으로 아는데, 간단한 내용이라면 이상과 같이 ChatGPT에게 적절한 Prompt 를 입력해주는 것만으로도 충분히 도움을 받을 수 있을 것 같다. 필자는 이상과 같은 방법으로 퇴근 후 적은 시간을 투자했음에도 불구하고 20개 이상의 엔티티 클래스와 레포지터리 인터페이스 작성 및 테스트 작업을 단 며칠만에 마무리할 수 있었다.
'KAKAO CHATBOT' 카테고리의 다른 글
[AI 활용과 개발] ChatGPT 를 활용해 스프링의 핵심원리 (DI, IOC) 관련 코드 작성하기 (ApplicationContext 사용하기) (0) | 2024.05.09 |
---|---|
[AI 활용과 개발] 카카오 빌더 개발문서 참고하여 필수 테이블 설계하기 (0) | 2024.05.08 |
[AI 활용과 개발] ChatGPT 를 통해 ChatGPT 더 알아보기 (1) | 2024.05.06 |
[AI 활용과 개발] ChatGPT 가 안 좋아할 질문 해보기 (0) | 2024.02.06 |
[주요 개념] 모두 보기 (0) | 2023.07.15 |