다들 아시다시피 jpa의 ddl-auto는 create, create-drop, update 옵션을 사용하면 엔티티를 만들면 자동으로 DDL을 작성하여 테이블을 생성하고 수정하는 편리한 기능입니다. 하지만 운영환경에서도 이 기능을 적용하면 실수로 테이블이 삭제되거나 변경사항이 적용되지 않은 채 배포되는 등 문제를 일으킬 수 있기때문에 validate 나 none 옵션을 사용합니다.
프로젝트를 진행하다 테이블 컬럼을 추가해야되는 일이 생겼는데 구글링을 하던 도중 flyway라는 라이브러리를 알게되어 적용시켜 보았습니다.
Flyway 란
flyway는 데이터베이스의 형상관리를 목적으로 사용하는 툴입니다. Git을 사용하여 코드를 관리하는 것 같이 flyway는 데이터베이스의 DDL 버전을 쌓아가면서 이력을 추적하고 관리할 수 있습니다.
Flyway 적용하기
저는 이미 생성된 테이블이 있는 운영서버에 적용시켰기 때문에 기존 테이블이 있다고 가정겠습니다.
의존성 설정
dependencies {
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
}
mysql 8.0 이상을 사용하시는 분이라면 추가적으로 적용하면 됩니다.
application.yaml
spring:
flyway:
enable: true
baseline-on-migrate: true
datasource:
url: url
driver-class-name: com.mysql.cj.jdbc.Driver
username: usernamae
password: password
jpa:
properties:
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: validate
show-sql: true
enable : flyway를 사용하겠다는 설정입니다.
baseline-on-migrate : flyway 버전을 관리하는 flyway_schema_history 테이블을 생성하는 옵션입니다. 히스토리 테이블이 존재하지 않기 때문에 true옵션을 사용했습니다.
ddl-auto : jpa ddl-auto 옵션을 validate 나 none으로 바꿔줍니다.
스크립트 파일 작성
V1 스크립트 파일을 작성합니다. 비어있는 스크립트여도 상관없지만, 로컬에서도 적용시킬 예정이고 같이 프로젝트를 진행하시는 분이 있기 때문에 생성되어있는 테이블의 DDL을 작성했습니다.
V1__init.sql
# V1__init.sql
create table student_lesson
(
student_lesson_id bigint auto_increment
primary key,
focus_status bit null,
lesson_id bigint null,
student_id bigint null,
constraint FK2nmxs05vgk43xy1cko182p72p
foreign key (student_id) references student (student_id),
constraint FKa64mwri6gq3ai7jwih91gsmf7
foreign key (lesson_id) references lesson (lesson_id)
);
스크립트 파일은 resource/db/migration 폴더아래 위치해야하고 만약 원하는 위치를 지정하고 싶으면 properties에서
spring.flyway.locations 옵션에서 경로를 직접 적어주시면 됩니다.
DB 적용 확인하기
과정이 모두 진행하고 앱을 실행시키면 DB에 flyway_schema_history 테이블이 생기며 적용된 것을 확인할 수 있습니다.
컬럼 추가하기
이제 작성되어있는 Entity에 컬럼을 추가하겠습니다.
@Entity
@Table(name = "student_lesson")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StudentLessonJpaEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "student_lesson_id")
private Long id;
@Column
private boolean focusStatus;
@Column
private boolean isDeleted;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "lesson_id")
private LessonJpaEntity lessonJpaEntity;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "student_id")
private StudentJpaEntity studentJpaEntity;
@Builder
public StudentLessonJpaEntity(Long id, boolean focusStatus, boolean isDeleted,
LessonJpaEntity lessonJpaEntity, StudentJpaEntity studentJpaEntity) {
this.id = id;
this.focusStatus = focusStatus;
this.isDeleted = isDeleted;
this.lessonJpaEntity = lessonJpaEntity;
this.studentJpaEntity = studentJpaEntity;
}
}
제가 추가한 부분은 isDeleted 입니다. 스크립트를 추가 작성하기에 앞서 어플리케이션을 다시 실행시키면 다음과 같이 ddl-auto validate 옵션에 의해 is_deleted 컬럼이 테이블에 존재하지 않는다고 에러가 발생하면서 실행되지 않습니다.
그럼 이제 V2 컬럼추가 스크립트를 작성하겠습니다.
# V2__add_isDeleted_column.sql
ALTER TABLE student_lesson ADD COLUMN is_deleted bit NOT NULL DEFAULT 0;
스크립트를 추가해주고 다시 어플리케이션을 실행시키면 flyway history 테이블의 버전이 업데이트되고 스크립트에 작성한 컬럼도 추가된 것을 확인할 수 있습니다.
flyway_schema_history
student_lesson table
참고
https://backtony.github.io/spring/2021-10-22-spring-db-1/
Spring - Flyway 적용하기
Java, JPA, Spring을 주로 다루고 공유합니다.
backtony.github.io
https://stackoverflow.com/questions/72711770/flyway-unsupported-database-mysql-8-0
flyway : Unsupported Database: MySQL 8.0
I am using java 11, and I have added flyway in spring-boot application like below. dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation group: 'my...
stackoverflow.com
https://documentation.red-gate.com/fd/quickstart-how-flyway-works-184127223.html
Quickstart - How Flyway Works - Flyway - Product Documentation
Events & Friends Meet us at an event, get sponsored, and join our Friends of Redgate
documentation.red-gate.com
'spring' 카테고리의 다른 글
Spring Security CORS 이슈 해결 - Preflight 403 Invalid CORS request (1) | 2023.10.10 |
---|---|
Java 17, Spring boot 3 알아보기 (0) | 2023.08.28 |
Spring SQLIntegrityConstraintViolationException cannot add or update a child row 해결 (0) | 2023.08.20 |