Merge pull request #9 from beaniejoy/feature/7
flyway를 통한 db migration 적용
This commit is contained in:
@@ -3,6 +3,7 @@ buildscript {
|
||||
springBootVersion = '2.7.0'
|
||||
dependencyManagementVersion = '1.0.11.RELEASE'
|
||||
kotlinVersion = '1.6.21'
|
||||
flywayVersion = '7.15.0'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -44,6 +45,7 @@ dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
|
||||
|
||||
implementation('io.github.microutils:kotlin-logging:2.1.21')
|
||||
|
||||
@@ -60,6 +62,8 @@ dependencies {
|
||||
runtimeOnly 'mysql:mysql-connector-java' // MySQL
|
||||
runtimeOnly 'com.h2database:h2' // H2
|
||||
|
||||
implementation "org.flywaydb:flyway-core:${flywayVersion}" // flyway
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.beaniejoy.dongnecafe.common.entity
|
||||
|
||||
import org.springframework.data.domain.AuditorAware
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.*
|
||||
|
||||
@Component
|
||||
class BaseEntityAuditorAware: AuditorAware<String> {
|
||||
override fun getCurrentAuditor(): Optional<String> {
|
||||
// TODO 추후 사용자 로그인 기능 추가되면 실제 등록한 사용자를 DB에 저장하는 방향으로 수정
|
||||
return Optional.of("system")
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.beaniejoy.dongnecafe.common.domain
|
||||
package io.beaniejoy.dongnecafe.common.entity
|
||||
|
||||
import org.springframework.data.annotation.CreatedBy
|
||||
import org.springframework.data.annotation.CreatedDate
|
||||
import org.springframework.data.annotation.LastModifiedBy
|
||||
import org.springframework.data.annotation.LastModifiedDate
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener
|
||||
import java.time.LocalDateTime
|
||||
@@ -9,10 +11,16 @@ import javax.persistence.MappedSuperclass
|
||||
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditingEntityListener::class)
|
||||
open class BaseTimeEntity(
|
||||
class BaseTimeEntity(
|
||||
@CreatedDate
|
||||
val createdAt: LocalDateTime = LocalDateTime.now(),
|
||||
|
||||
@CreatedBy
|
||||
val createdBy: String = "",
|
||||
|
||||
@LastModifiedDate
|
||||
val updatedAt: LocalDateTime? = null
|
||||
val updatedAt: LocalDateTime? = null,
|
||||
|
||||
@LastModifiedBy
|
||||
val updatedBy: String? = null
|
||||
)
|
||||
@@ -17,7 +17,7 @@ class CafeController(
|
||||
) {
|
||||
@GetMapping
|
||||
fun searchCafeList(
|
||||
@PageableDefault(sort = ["name"], direction = Sort.Direction.ASC, size = 10) pageable: Pageable
|
||||
@PageableDefault(sort = ["name"], direction = Sort.Direction.ASC, page = 0, size = 10) pageable: Pageable
|
||||
): Page<CafeSearchResponseDto> {
|
||||
return cafeService.getCafeList(pageable)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ data class OptionDetailResponseDto(
|
||||
return OptionDetailResponseDto(
|
||||
id = optionDetail.id,
|
||||
name = optionDetail.name,
|
||||
extra = optionDetail.extra
|
||||
extra = optionDetail.extraPrice
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.entity
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.entity
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.entity
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity
|
||||
import java.math.BigDecimal
|
||||
import javax.persistence.*
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.entity
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity
|
||||
import javax.persistence.*
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.beaniejoy.dongnecafe.domain.cafe.entity
|
||||
|
||||
import io.beaniejoy.dongnecafe.common.domain.BaseTimeEntity
|
||||
import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity
|
||||
import java.math.BigDecimal
|
||||
import javax.persistence.*
|
||||
|
||||
@@ -14,11 +14,10 @@ class OptionDetail(
|
||||
@Column(name = "name", nullable = false)
|
||||
val name: String,
|
||||
|
||||
@Column(name = "extra", nullable = false)
|
||||
val extra: BigDecimal,
|
||||
@Column(name = "extra_price", nullable = false)
|
||||
val extraPrice: BigDecimal,
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "option_id", nullable = false)
|
||||
val menuOption: MenuOption
|
||||
): BaseTimeEntity() {
|
||||
}
|
||||
): BaseTimeEntity()
|
||||
@@ -2,8 +2,10 @@ package io.beaniejoy.dongnecafe.domain.cafe.service
|
||||
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeInfoResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.dto.cafe.CafeSearchResponseDto
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.entity.Cafe
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.error.CafeNotFoundException
|
||||
import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeRepository
|
||||
import mu.KLogging
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
@@ -15,12 +17,13 @@ import org.springframework.transaction.annotation.Transactional
|
||||
class CafeService(
|
||||
private val cafeRepository: CafeRepository
|
||||
) {
|
||||
companion object: KLogging()
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getCafeList(pageable: Pageable): Page<CafeSearchResponseDto> {
|
||||
val cafeListWithPagination = cafeRepository.findAll(pageable)
|
||||
val cafeList: Page<Cafe> = cafeRepository.findAll(pageable)
|
||||
|
||||
return cafeListWithPagination.map { CafeSearchResponseDto.of(it) }
|
||||
return cafeList.map { CafeSearchResponseDto.of(it) }
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb;MODE=MySQL
|
||||
url: jdbc:mysql://localhost:3306/dongne?autoreconnect=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
|
||||
username: root
|
||||
password: beaniejoy # TODO 추후 보안에 대해 생각해보기
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
ddl-auto: none # flyway migration 사용
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
format_sql: true
|
||||
show-sql: true
|
||||
flyway:
|
||||
baseline-on-migrate: true
|
||||
locations: classpath:db/migration,classpath:db/seed
|
||||
# baseline-version: 0
|
||||
|
||||
15
src/main/resources/db/migration/V001__Create_cafe.sql
Normal file
15
src/main/resources/db/migration/V001__Create_cafe.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `cafe`;
|
||||
|
||||
CREATE TABLE `cafe` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '카페 ID',
|
||||
`name` varchar(20) NOT NULL COMMENT '카페명',
|
||||
`address` varchar(100) NOT NULL COMMENT '카페 주소',
|
||||
`phone_number` varchar(11) NOT NULL COMMENT '카페 전화번호',
|
||||
`total_rate` float NOT NULL COMMENT '카페 종합 평가 점수',
|
||||
`description` varchar(255) COMMENT '카페 상세설명',
|
||||
`created_at` datetime NOT NULL COMMENT '카페 등록날짜',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '카페 등록자',
|
||||
`updated_at` datetime NULL COMMENT '카페 변경날짜',
|
||||
`updated_by` varchar(20) NULL COMMENT '카페 변경자',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
15
src/main/resources/db/migration/V002__Create_cafe_menu.sql
Normal file
15
src/main/resources/db/migration/V002__Create_cafe_menu.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `cafe_menu`;
|
||||
|
||||
CREATE TABLE `cafe_menu` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '카페 메뉴 ID',
|
||||
`name` varchar(50) NOT NULL COMMENT '카페 메뉴명',
|
||||
`price` decimal(10, 2) NOT NULL COMMENT '메뉴 가격',
|
||||
`created_at` datetime NOT NULL COMMENT '메뉴 등록날짜',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '메뉴 등록자',
|
||||
`updated_at` datetime COMMENT '메뉴 변경날짜',
|
||||
`updated_by` varchar(20) NULL COMMENT '메뉴 변경자',
|
||||
`cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `cafe_id` (`cafe_id`),
|
||||
FOREIGN KEY (`cafe_id`) REFERENCES `cafe` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
14
src/main/resources/db/migration/V003__Create_cafe_image.sql
Normal file
14
src/main/resources/db/migration/V003__Create_cafe_image.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS `cafe_image`;
|
||||
|
||||
CREATE TABLE `cafe_image` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '카페 이미지 ID',
|
||||
`img_url` varchar(255) NOT NULL COMMENT '이미지 경로',
|
||||
`created_at` datetime NOT NULL COMMENT '이미지 등록날짜',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '이미지 등록자',
|
||||
`updated_at` datetime COMMENT '이미지 변경날짜',
|
||||
`updated_by` varchar(20) NULL COMMENT '이미지 변경자',
|
||||
`cafe_id` bigint unsigned NOT NULL COMMENT '연관된 카페 ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `cafe_id` (`cafe_id`),
|
||||
FOREIGN KEY (`cafe_id`) REFERENCES `cafe` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
14
src/main/resources/db/migration/V004__Create_menu_option.sql
Normal file
14
src/main/resources/db/migration/V004__Create_menu_option.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS `menu_option`;
|
||||
|
||||
CREATE TABLE `menu_option`(
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '옵션 ID',
|
||||
`title` varchar(50) NOT NULL COMMENT '메뉴 옵션 이름',
|
||||
`created_at` datetime NOT NULL COMMENT '옵션 등록날짜',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '옵션 등록자',
|
||||
`updated_at` datetime COMMENT '옵션 변경날짜',
|
||||
`updated_by` varchar(20) NULL COMMENT '옵션 변경자',
|
||||
`menu_id` bigint unsigned NOT NULL COMMENT '연관된 카페 메뉴 ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `menu_id` (`menu_id`),
|
||||
FOREIGN KEY (`menu_id`) REFERENCES `cafe_menu` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS `option_detail`;
|
||||
|
||||
CREATE TABLE `option_detail` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '옵션 상세 ID',
|
||||
`name` varchar(50) NOT NULL COMMENT '옵션 상세명',
|
||||
`extra_price` decimal(10, 2) NOT NULL COMMENT '옵션 추가 요금',
|
||||
`created_at` datetime NOT NULL COMMENT '옵션 상세 등록날짜',
|
||||
`created_by` varchar(20) NOT NULL COMMENT '옵션 상세 등록자',
|
||||
`updated_at` datetime COMMENT '옵션 상세 변경날짜',
|
||||
`updated_by` varchar(20) NULL COMMENT '옵션 상세 변경자',
|
||||
`option_id` bigint unsigned NOT NULL COMMENT '연관된 옵션 ID',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `option_id` (`option_id`),
|
||||
FOREIGN KEY (`option_id`) REFERENCES `menu_option` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
20
src/main/resources/db/seed/R__Insert_Seed_cafe.sql
Normal file
20
src/main/resources/db/seed/R__Insert_Seed_cafe.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('비니카페', '서울시 동대문구 전농로', '01011112222', 3.98, '언제나 상쾌한 비니카페', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('조이카페', '서울시 영등포구', '01033334444', 4.67, '언제나 상쾌한 조이카페', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('abc카페', '서울시 서대문구', '01025341432', 4.89, '언제나 상쾌한 abc카페', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('동네주변카페', '서울시 송파구', '01022223333', 4.23, '언제나 상쾌한 동네주변카페', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('방긋카페', '서울시 광진구', '01099998888', 4.35, '언제나 상쾌한 방긋카페', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('example cafe1', '서울시 종로구', '01077779999', 2.85, '언제나 상쾌한 example cafe1', now(), 'system', null, null);
|
||||
|
||||
INSERT IGNORE INTO `cafe` (name, address, phone_number, total_rate, description, created_at, created_by, updated_at, updated_by)
|
||||
VALUES ('example cafe2', '서울시', '01044445555', 3.12, '언제나 상쾌한 example cafe2', now(), 'system', null, null);
|
||||
26
src/main/resources/db/seed/R__Insert_Seed_cafe_image.sql
Normal file
26
src/main/resources/db/seed/R__Insert_Seed_cafe_image.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
DROP PROCEDURE IF EXISTS insertCafeImages;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE insertCafeImages()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 0;
|
||||
DECLARE j INT;
|
||||
DECLARE idx_img INT DEFAULT 1;
|
||||
DECLARE var_cafe_id binary(16);
|
||||
DECLARE count_cafe INT;
|
||||
SET count_cafe = (SELECT COUNT(*) FROM `cafe`);
|
||||
WHILE(i <= count_cafe) DO
|
||||
SET j = 1;
|
||||
SET var_cafe_id = (SELECT id FROM `cafe` LIMIT i, 1);
|
||||
WHILE(j <= 3) DO
|
||||
INSERT IGNORE INTO `cafe_image` (img_url, created_at, created_by, updated_at, updated_by, cafe_id)
|
||||
VALUES (CONCAT('test_img_url_', idx_img), now(), 'system', null, null, var_cafe_id);
|
||||
SET j = j + 1;
|
||||
SET idx_img = idx_img + 1;
|
||||
END WHILE;
|
||||
SET i = i + 1;
|
||||
END WHILE;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
CALL insertCafeImages();
|
||||
22
src/main/resources/db/seed/R__Insert_Seed_cafe_menu.sql
Normal file
22
src/main/resources/db/seed/R__Insert_Seed_cafe_menu.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
DROP PROCEDURE IF EXISTS insertCafeMenus;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE insertCafeMenus()
|
||||
BEGIN
|
||||
DECLARE i INT DEFAULT 0;
|
||||
DECLARE j INT;
|
||||
DECLARE var_cafe_id binary(16);
|
||||
WHILE(i <= 4) DO
|
||||
SET j = 1;
|
||||
SET var_cafe_id = (SELECT id FROM `cafe` LIMIT i, 1);
|
||||
WHILE(j <= 10) DO
|
||||
INSERT IGNORE INTO `cafe_menu` (name, price, created_at, created_by, updated_at, updated_by, cafe_id)
|
||||
VALUES (CONCAT('커피', j), FLOOR(RAND() * 10 + 1) * 1000, now(), 'system', null, null, var_cafe_id);
|
||||
SET j = j + 1;
|
||||
END WHILE;
|
||||
SET i = i + 1;
|
||||
END WHILE;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
CALL insertCafeMenus();
|
||||
Reference in New Issue
Block a user