From 8f22cdcbb846a3d98bd204d3d45883746bfc1b36 Mon Sep 17 00:00:00 2001 From: LeeGeonHo Date: Sat, 16 Mar 2024 11:31:57 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=EB=A1=9C?= =?UTF-8?q?=20=EB=8F=99=EC=9E=91=ED=95=A0=20=EC=88=98=20=EC=9E=88=EA=B2=8C?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20(#44)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: flyway 추가 * refactor: 환경 변수로 값 지정할 수 있게 yml 변경 * build: CD에서 jar로 이미지 만들 수 있게 도커파일 추가 * refactor: 직접 참조 간접 참조로 변경 * refactor: 매 정각, 30분 마다 api 호출하도록 변경 --- Dockerfile | 5 ++ build.gradle | 4 + .../SearchConditionService.java | 9 +- .../searchcondition/SearchCondition.java | 79 +++++++++-------- .../scheduler/ParkingUpdateScheduler.java | 2 +- src/main/resources/application-dev.yml | 11 +++ src/main/resources/application-prod.yml | 22 +++++ src/main/resources/application.yml | 40 ++++----- .../mysql/V1.0.0__initial_schema.sql | 88 +++++++++++++++++++ src/test/resources/application.yml | 6 +- 10 files changed, 193 insertions(+), 73 deletions(-) create mode 100644 Dockerfile create mode 100644 src/main/resources/application-dev.yml create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/db/migration/mysql/V1.0.0__initial_schema.sql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..de65fcf8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM amazoncorretto:17-alpine + +COPY build/libs/parking-0.0.1-SNAPSHOT.jar app.jar + +CMD ["java", "-jar", "app.jar"] diff --git a/build.gradle b/build.gradle index 914c9532..da6970ca 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,10 @@ dependencies { testImplementation "org.testcontainers:junit-jupiter:1.19.6" testImplementation "com.redis:testcontainers-redis:2.2.0" testImplementation "org.testcontainers:mysql:1.19.6" + + // flyway 추가 + implementation 'org.flywaydb:flyway-mysql' + implementation 'org.flywaydb:flyway-core' } tasks.named('test') { diff --git a/src/main/java/com/example/parking/application/searchcondition/SearchConditionService.java b/src/main/java/com/example/parking/application/searchcondition/SearchConditionService.java index cf15d040..dc36abe7 100644 --- a/src/main/java/com/example/parking/application/searchcondition/SearchConditionService.java +++ b/src/main/java/com/example/parking/application/searchcondition/SearchConditionService.java @@ -1,17 +1,16 @@ package com.example.parking.application.searchcondition; import com.example.parking.application.searchcondition.dto.SearchConditionDto; -import com.example.parking.domain.member.Member; -import com.example.parking.domain.member.MemberRepository; import com.example.parking.domain.parking.OperationType; import com.example.parking.domain.parking.ParkingType; import com.example.parking.domain.parking.PayType; -import com.example.parking.domain.searchcondition.SearchConditionAvailable; import com.example.parking.domain.searchcondition.FeeType; import com.example.parking.domain.searchcondition.Hours; import com.example.parking.domain.searchcondition.Priority; import com.example.parking.domain.searchcondition.SearchCondition; +import com.example.parking.domain.searchcondition.SearchConditionAvailable; import com.example.parking.domain.searchcondition.SearchConditionRepository; +import com.example.parking.support.Association; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,7 +22,6 @@ public class SearchConditionService { private final SearchConditionRepository searchConditionRepository; - private final MemberRepository memberRepository; public SearchConditionDto findSearchCondition(Long memberId) { SearchCondition searchCondition = searchConditionRepository.getByMemberId(memberId); @@ -58,9 +56,8 @@ public void updateSearchCondition(Long memberId, SearchConditionDto searchCondit } private SearchCondition createSearchCondition(Long memberId, SearchConditionDto searchConditionDto) { - Member member = memberRepository.getById(memberId); return new SearchCondition( - member, + Association.from(memberId), toEnums(searchConditionDto.getOperationType(), OperationType.values()), toEnums(searchConditionDto.getParkingType(), ParkingType.values()), toEnums(searchConditionDto.getFeeType(), FeeType.values()), diff --git a/src/main/java/com/example/parking/domain/searchcondition/SearchCondition.java b/src/main/java/com/example/parking/domain/searchcondition/SearchCondition.java index e9ddb5ba..9b55c910 100644 --- a/src/main/java/com/example/parking/domain/searchcondition/SearchCondition.java +++ b/src/main/java/com/example/parking/domain/searchcondition/SearchCondition.java @@ -8,17 +8,17 @@ import com.example.parking.infra.converter.OperationTypeConverter; import com.example.parking.infra.converter.ParkingTypeConverter; import com.example.parking.infra.converter.PayTypeConverter; +import com.example.parking.support.Association; +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToOne; import java.util.List; import lombok.AccessLevel; import lombok.Getter; @@ -29,49 +29,50 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class SearchCondition { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn - private Member member; + @Embedded + @AttributeOverride(name = "id", column = @Column(name = "member_id")) + private Association memberId; - @Convert(converter = OperationTypeConverter.class) - private List operationTypes; + @Convert(converter = OperationTypeConverter.class) + private List operationTypes; - @Convert(converter = ParkingTypeConverter.class) - private List parkingTypes; + @Convert(converter = ParkingTypeConverter.class) + private List parkingTypes; - @Convert(converter = FeeTypeConverter.class) - private List feeTypes; + @Convert(converter = FeeTypeConverter.class) + private List feeTypes; - @Convert(converter = PayTypeConverter.class) - private List payTypes; + @Convert(converter = PayTypeConverter.class) + private List payTypes; - @Enumerated(EnumType.STRING) - private Priority priority; + @Enumerated(EnumType.STRING) + private Priority priority; - @Embedded - private Hours hours; + @Embedded + private Hours hours; - public SearchCondition(Member member, List operationTypes, List parkingTypes, - List feeTypes, List payTypes, Priority priority, Hours hours) { - this.member = member; - this.operationTypes = operationTypes; - this.parkingTypes = parkingTypes; - this.feeTypes = feeTypes; - this.payTypes = payTypes; - this.priority = priority; - this.hours = hours; - } + public SearchCondition(Association memberId, List operationTypes, + List parkingTypes, + List feeTypes, List payTypes, Priority priority, Hours hours) { + this.memberId = memberId; + this.operationTypes = operationTypes; + this.parkingTypes = parkingTypes; + this.feeTypes = feeTypes; + this.payTypes = payTypes; + this.priority = priority; + this.hours = hours; + } - public void update(SearchCondition updated) { - this.operationTypes = updated.operationTypes; - this.parkingTypes = updated.parkingTypes; - this.feeTypes = updated.feeTypes; - this.payTypes = updated.payTypes; - this.priority = updated.priority; - this.hours = updated.hours; - } + public void update(SearchCondition updated) { + this.operationTypes = updated.operationTypes; + this.parkingTypes = updated.parkingTypes; + this.feeTypes = updated.feeTypes; + this.payTypes = updated.payTypes; + this.priority = updated.priority; + this.hours = updated.hours; + } } diff --git a/src/main/java/com/example/parking/external/scheduler/ParkingUpdateScheduler.java b/src/main/java/com/example/parking/external/scheduler/ParkingUpdateScheduler.java index e9bb856b..3de2c057 100644 --- a/src/main/java/com/example/parking/external/scheduler/ParkingUpdateScheduler.java +++ b/src/main/java/com/example/parking/external/scheduler/ParkingUpdateScheduler.java @@ -29,7 +29,7 @@ public class ParkingUpdateScheduler { private final CoordinateService coordinateService; private final ParkingService parkingService; - @Scheduled(fixedRate = 30, timeUnit = TimeUnit.MINUTES) + @Scheduled(cron = "0 */30 * * * *") public void autoUpdateOfferCurrentParking() { Map parkingLots = readBy(ParkingApiService::offerCurrentParking); Map saved = findAllByName(parkingLots.keySet()); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 00000000..22c29aa9 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,11 @@ +spring: + # JPA + jpa: + hibernate: + ddl-auto: create + show-sql: true + properties: + hibernate: + format_sql: true + flyway: + enabled: false diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..c7a26256 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,22 @@ +spring: + # JPA + jpa: + hibernate: + ddl-auto: validate + database: mysql + open-in-view: false + + # DB + datasource: + url: ${DB_URL} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + # flyway + flyway: + enabled: true + url: ${DB_URL} + user: ${DB_USERNAME} + password: ${DB_PASSWORD} + baseline-on-migrate: true + locations: classpath:db/migration/mysql diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a0e65bca..614ab88b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,17 +1,12 @@ spring: - jpa: - hibernate: - ddl-auto: create - show-sql: true - properties: - hibernate: - format_sql: true - # mail + profiles: + active: ${PROFILE:dev} +# MAIL mail: - host: smtp.gmail.com - port: 587 - username: everythinginparking3@gmail.com - password: test + host: ${MAIL_HOST:smtp.gmail.com} + port: ${MAIL_PORT:587} + username: ${MAIL_USERNAME:mail@gmail.com} + password: ${MAIL_PASSWORD:password} properties: mail: smtp: @@ -19,23 +14,18 @@ spring: timeout: 5000 starttls: enable: true - # redis +# REDIS data: redis: - host: localhost - port: 6379 - -# file -file: - dir: src/test/resources/static/images/ + host: ${REDIS_HOST:localhost} + port: ${REDIS_PORT:6379} -# authcode +# AUTH CODE authcode: expired-time: 300 - -# key +# API KEY kakao: - key: test -seoul-public-parking-key: test -pusan-public-parking-key: test + key: ${KAKAO_API_KEY:kakao} +seoul-public-parking-key: ${SEOUL_API_KEY:seoul} +pusan-public-parking-key: ${PUSAN_API_KEY:pusan} diff --git a/src/main/resources/db/migration/mysql/V1.0.0__initial_schema.sql b/src/main/resources/db/migration/mysql/V1.0.0__initial_schema.sql new file mode 100644 index 00000000..dd6ec735 --- /dev/null +++ b/src/main/resources/db/migration/mysql/V1.0.0__initial_schema.sql @@ -0,0 +1,88 @@ +-- favorite 테이블 생성 +CREATE TABLE favorite ( + id BIGINT NOT NULL AUTO_INCREMENT, + created_at TIMESTAMP, + updated_at TIMESTAMP, + member_id BIGINT, + parking_id BIGINT, + PRIMARY KEY (id), + UNIQUE (member_id, parking_id) +); + +-- member 테이블 생성 +CREATE TABLE member ( + id BIGINT NOT NULL AUTO_INCREMENT, + deleted BOOLEAN, + email VARCHAR(255) UNIQUE, + name VARCHAR(255), + nickname VARCHAR(255), + password VARCHAR(255), + PRIMARY KEY (id) +); + +-- member_session 테이블 생성 +CREATE TABLE member_session ( + session_id VARCHAR(255) NOT NULL, + created_at TIMESTAMP, + expired_at TIMESTAMP, + member_id BIGINT, + PRIMARY KEY (session_id) +); + +-- parking 테이블 생성 +CREATE TABLE parking ( + id BIGINT NOT NULL AUTO_INCREMENT, + created_at TIMESTAMP, + updated_at TIMESTAMP, + base_fee INTEGER, + base_time_unit INTEGER, + capacity INTEGER, + current_parking INTEGER, + day_maximum_fee INTEGER, + extra_fee INTEGER, + extra_time_unit INTEGER, + holiday_begin_time TIME, + holiday_end_time TIME, + holiday_free_begin_time TIME, + holiday_free_end_time TIME, + latitude FLOAT NOT NULL, + longitude FLOAT NOT NULL, + saturday_begin_time TIME, + saturday_end_time TIME, + saturday_free_begin_time TIME, + saturday_free_end_time TIME, + weekday_begin_time TIME, + weekday_end_time TIME, + weekday_free_begin_time TIME, + weekday_free_end_time TIME, + address VARCHAR(255), + description VARCHAR(255), + name VARCHAR(255), + operation_type ENUM ('PUBLIC', 'PRIVATE', 'NO_INFO'), + parking_type ENUM ('OFF_STREET', 'ON_STREET', 'MECHANICAL', 'NO_INFO'), + tel VARCHAR(255), + PRIMARY KEY (id) +); + +-- review 테이블 생성 +CREATE TABLE review ( + id BIGINT NOT NULL AUTO_INCREMENT, + created_at TIMESTAMP, + parking_id BIGINT, + reviewer_id BIGINT, + contents VARCHAR(255), + PRIMARY KEY (id) +); + +-- search_condition 테이블 생성 +CREATE TABLE search_condition ( + id BIGINT NOT NULL AUTO_INCREMENT, + hours INTEGER NOT NULL, + member_id BIGINT, + fee_types VARCHAR(255), + operation_types VARCHAR(255), + parking_types VARCHAR(255), + pay_types VARCHAR(255), + priority ENUM ('DISTANCE', 'PRICE', 'RECOMMENDATION'), + PRIMARY KEY (id) +); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 8d0ffec3..639fdc28 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -1,4 +1,6 @@ spring: + flyway: + enabled: false jpa: hibernate: ddl-auto: create @@ -9,7 +11,7 @@ spring: mail: host: smtp.gmail.com port: 587 - username: everythinginparking3@gmail.com + username: test@gmail.com password: test properties: mail: @@ -32,7 +34,7 @@ kakao: key: test seoul-public-parking-key: test -pusan-public-parking-key: test%2FbCRaddaK2FMoeVpVW2SqG%2B2cdn4Xdf1LpWru4O8opXbJc0wbbSdjXhQykcw2S8HmDuA%2BW3GiFFGDPgQ%3D%3D +pusan-public-parking-key: test authcode: expired-time: 60