diff --git a/build.gradle b/build.gradle index 65866bba..c977b087 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation group: 'org.hibernate', name: 'hibernate-spatial', version: '6.4.2.Final' + compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/src/main/java/com/m3pro/groundflip/domain/dto/pixel/IndividualPixelResponse.java b/src/main/java/com/m3pro/groundflip/domain/dto/pixel/IndividualPixelResponse.java index d911b884..68b580a2 100644 --- a/src/main/java/com/m3pro/groundflip/domain/dto/pixel/IndividualPixelResponse.java +++ b/src/main/java/com/m3pro/groundflip/domain/dto/pixel/IndividualPixelResponse.java @@ -16,6 +16,7 @@ public class IndividualPixelResponse { private double y; public static IndividualPixelResponse from(Pixel pixel) { - return new IndividualPixelResponse(pixel.getLatitude(), pixel.getLongitude(), pixel.getX(), pixel.getY()); + return new IndividualPixelResponse(pixel.getCoordinate().getX(), pixel.getCoordinate().getY(), pixel.getX(), + pixel.getY()); } } diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/Community.java b/src/main/java/com/m3pro/groundflip/domain/entity/Community.java index 8895c6ff..bc110187 100644 --- a/src/main/java/com/m3pro/groundflip/domain/entity/Community.java +++ b/src/main/java/com/m3pro/groundflip/domain/entity/Community.java @@ -1,5 +1,7 @@ package com.m3pro.groundflip.domain.entity; +import java.time.LocalDateTime; + import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; import jakarta.persistence.Column; @@ -35,4 +37,6 @@ public class Community extends BaseTimeEntity { private String backgroundImageUrl; private String description; + + private LocalDateTime deletedAt; } diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/Pixel.java b/src/main/java/com/m3pro/groundflip/domain/entity/Pixel.java index 97c36242..b9285a97 100644 --- a/src/main/java/com/m3pro/groundflip/domain/entity/Pixel.java +++ b/src/main/java/com/m3pro/groundflip/domain/entity/Pixel.java @@ -1,17 +1,14 @@ package com.m3pro.groundflip.domain.entity; +import org.locationtech.jts.geom.Point; + import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.Index; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -20,7 +17,6 @@ @Getter @Entity -@Table(name = "pixel", indexes = @Index(name = "index__x__y", columnList = "x, y")) @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder @@ -34,11 +30,10 @@ public class Pixel extends BaseTimeEntity { private Long y; - private double latitude; + @Column(columnDefinition = "POINT SRID 4326 NOT NULL") + private Point coordinate; - private double longitude; + private String address; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id") - private User user; + private Integer addressNumber; } diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/PixelUser.java b/src/main/java/com/m3pro/groundflip/domain/entity/PixelUser.java new file mode 100644 index 00000000..14fa3e32 --- /dev/null +++ b/src/main/java/com/m3pro/groundflip/domain/entity/PixelUser.java @@ -0,0 +1,47 @@ +package com.m3pro.groundflip.domain.entity; + +import java.time.LocalDateTime; + +import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "pixel_user") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class PixelUser extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "pixel_user_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "pixel_id") + private Pixel pixel; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "community_id") + private Community community; + + private LocalDateTime deletedAt; +} diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/StepRecord.java b/src/main/java/com/m3pro/groundflip/domain/entity/StepRecord.java new file mode 100644 index 00000000..5f24f446 --- /dev/null +++ b/src/main/java/com/m3pro/groundflip/domain/entity/StepRecord.java @@ -0,0 +1,34 @@ +package com.m3pro.groundflip.domain.entity; + +import java.sql.Date; + +import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "step_record") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class StepRecord extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "step_record_id") + private Long id; + + private Date date; + + private Integer steps; +} diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/User.java b/src/main/java/com/m3pro/groundflip/domain/entity/User.java index 3ece8250..39af7d9e 100644 --- a/src/main/java/com/m3pro/groundflip/domain/entity/User.java +++ b/src/main/java/com/m3pro/groundflip/domain/entity/User.java @@ -1 +1,48 @@ -package com.m3pro.groundflip.domain.entity; import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @Entity @Table(name = "user") @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder public class User extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") private Long id; private String nickname; } \ No newline at end of file +package com.m3pro.groundflip.domain.entity; + +import java.util.Date; + +import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; +import com.m3pro.groundflip.enums.Gender; +import com.m3pro.groundflip.enums.Provider; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Pattern; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "user") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class User extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") + private Long id; + + @Pattern(regexp = "[가-힣a-zA-Z0-9]{3,10}", message = "닉네임은 한글, 영어, 숫자를 조합해 3글자 이상, 10글자 이하입니다.") + private String nickname; + + private Date birthYear; + + private Gender gender; + + private Provider provider; + + @Email + private String email; + + private Date deletedAt; +} diff --git a/src/main/java/com/m3pro/groundflip/domain/entity/UserCommunity.java b/src/main/java/com/m3pro/groundflip/domain/entity/UserCommunity.java index 51034d6c..1d9dcb45 100644 --- a/src/main/java/com/m3pro/groundflip/domain/entity/UserCommunity.java +++ b/src/main/java/com/m3pro/groundflip/domain/entity/UserCommunity.java @@ -1 +1,43 @@ -package com.m3pro.groundflip.domain.entity; import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @Entity @Table(name = "user_community") @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder public class UserCommunity extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_community_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "community_id") private Community community; } \ No newline at end of file +package com.m3pro.groundflip.domain.entity; + +import java.time.LocalDateTime; + +import com.m3pro.groundflip.domain.entity.global.BaseTimeEntity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "user_community") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class UserCommunity extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_community_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "community_id") + private Community community; + + private LocalDateTime deletedAt; +} diff --git a/src/main/java/com/m3pro/groundflip/enums/Gender.java b/src/main/java/com/m3pro/groundflip/enums/Gender.java new file mode 100644 index 00000000..be611b28 --- /dev/null +++ b/src/main/java/com/m3pro/groundflip/enums/Gender.java @@ -0,0 +1,13 @@ +package com.m3pro.groundflip.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum Gender { + MALE("남성"), + FEMALE("여성"); + + private final String gender; +} diff --git a/src/main/java/com/m3pro/groundflip/enums/Provider.java b/src/main/java/com/m3pro/groundflip/enums/Provider.java new file mode 100644 index 00000000..7cd5743d --- /dev/null +++ b/src/main/java/com/m3pro/groundflip/enums/Provider.java @@ -0,0 +1,15 @@ +package com.m3pro.groundflip.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum Provider { + MALE("네이버"), + GOOGLE("구글"), + APPLE("애플"), + KAKAO("카카오"); + + private final String provider; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0dbcf687..c6289352 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,6 +9,7 @@ spring: password: ${DB_PASSWORD} jpa: + database-platform: org.hibernate.spatial.dialect.mysql.MySQL56InnoDBSpatialDialect hibernate: ddl-auto: update properties: diff --git a/src/main/resources/static/pixel_insert.sql b/src/main/resources/static/pixel_insert.sql index 6c921caa..57df1431 100644 --- a/src/main/resources/static/pixel_insert.sql +++ b/src/main/resources/static/pixel_insert.sql @@ -1 +1,35 @@ -DROP PROCEDURE IF EXISTS insertPixel; DELIMITER $$ CREATE PROCEDURE insertPixel () BEGIN DECLARE lat_per_pixel DOUBLE DEFAULT 0.0000724; DECLARE lon_per_pixel DOUBLE DEFAULT 0.000909; DECLARE upper_left_lat DOUBLE DEFAULT 38.240675; DECLARE upper_left_lon DOUBLE DEFAULT 125.905952; DECLARE current_lat DOUBLE; DECLARE current_lon DOUBLE; DECLARE i BIGINT DEFAULT 0; DECLARE j BIGINT DEFAULT 0; SET current_lat = upper_left_lat; SET current_lon = upper_left_lon; WHILE i < 7000 DO START TRANSACTION; SET current_lat = upper_left_lat - (i * lat_per_pixel); SET j = 0; WHILE j < 4156 DO SET current_lon = upper_left_lon + (j * lon_per_pixel); INSERT INTO pixel (latitude, longitude, x, y, created_at, modified_at) VALUES (current_lat, current_lon, i, j, NOW(), NOW()); SET j = j + 1; END WHILE; SET current_lon = upper_left_lon; -- Reset current longitude to the initial value SET i = i + 1; COMMIT; END WHILE; END $$ DELIMITER ; -- Call the stored procedure to insert the coordinates CALL InsertPixel(); \ No newline at end of file +DROP PROCEDURE IF EXISTS insertPixel; +DELIMITER $$ +CREATE PROCEDURE insertPixel() +BEGIN + DECLARE lat_per_pixel DOUBLE DEFAULT 0.0000724; + DECLARE lon_per_pixel DOUBLE DEFAULT 0.000909; + DECLARE upper_left_lat DOUBLE DEFAULT 38.240675; + DECLARE upper_left_lon DOUBLE DEFAULT 125.905952; + DECLARE current_lat DOUBLE; + DECLARE current_lon DOUBLE; + DECLARE i BIGINT DEFAULT 0; + DECLARE j BIGINT DEFAULT 0; + SET current_lat = upper_left_lat; + SET current_lon = upper_left_lon; + START TRANSACTION; + WHILE i < 7000 + DO + SET current_lat = upper_left_lat - (i * lat_per_pixel); + SET j = 0; + WHILE j < 4156 + DO + SET current_lon = upper_left_lon + (j * lon_per_pixel); + INSERT INTO pixel (coordinate, x, y, created_at, modified_at) + VALUES (ST_GeomFromText(CONCAT('POINT(', current_lat, ' ', current_lon, ')'), 4326), i, j, NOW(), + NOW()); + SET j = j + 1; + END WHILE; + SET current_lon = upper_left_lon; -- Reset current longitude to the initial value + SET i = i + 1; + END WHILE; + COMMIT; +END $$ +DELIMITER ; +-- Call the stored procedure to insert the coordinates +CALL InsertPixel(); \ No newline at end of file