Skip to content

Commit d6d4f6c

Browse files
committed
merge: feature/maps into develop
2 parents a46e876 + 1488323 commit d6d4f6c

31 files changed

+1140
-208
lines changed

build.gradle.kts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ dependencies {
3535
implementation("org.springframework.boot:spring-boot-starter-data-redis")
3636
implementation("mysql:mysql-connector-java:8.0.33")
3737

38+
implementation ("org.antlr:antlr4-runtime:4.10.1")
39+
40+
41+
// PostgreSQL + PostGIS
42+
implementation("org.postgresql:postgresql:42.7.3") // 최신 버전 확인
43+
implementation ("org.hibernate.orm:hibernate-spatial:6.2.7.Final") // 최신 Hibernate 6
44+
implementation("org.hibernate.orm:hibernate-core:6.2.7.Final")
45+
46+
// Geometry 관련
47+
implementation ("org.locationtech.jts:jts-core:1.18.2")
48+
3849
compileOnly("org.projectlombok:lombok")
3950
testCompileOnly("org.projectlombok:lombok")
4051
testAnnotationProcessor("org.projectlombok:lombok")

docker-compose.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
services:
2+
postgres:
3+
image: postgis/postgis:15-3.3
4+
container_name: log4u_postgres
5+
environment:
6+
POSTGRES_DB: gis_db
7+
POSTGRES_USER: postgres
8+
POSTGRES_PASSWORD: 1234
9+
ports:
10+
- "5432:5432"
11+
volumes:
12+
- pgdata:/var/lib/postgresql/data
13+
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql
14+
networks:
15+
- log4u-net
16+
17+
volumes:
18+
pgdata:
19+
20+
networks:
21+
log4u-net:
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.example.log4u.common.config;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import javax.sql.DataSource;
7+
8+
import org.springframework.boot.context.properties.ConfigurationProperties;
9+
import org.springframework.boot.jdbc.DataSourceBuilder;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.context.annotation.Primary;
13+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
14+
import org.springframework.orm.jpa.JpaTransactionManager;
15+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
16+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
17+
import org.springframework.transaction.PlatformTransactionManager;
18+
19+
@Configuration
20+
@EnableJpaRepositories(
21+
basePackages = {
22+
"com.example.log4u.common",
23+
"com.example.log4u.domain.comment",
24+
"com.example.log4u.domain.diary",
25+
"com.example.log4u.domain.follow",
26+
"com.example.log4u.domain.like",
27+
"com.example.log4u.domain.media",
28+
"com.example.log4u.domain.reports",
29+
"com.example.log4u.domain.supports",
30+
"com.example.log4u.domain.user"
31+
},
32+
entityManagerFactoryRef = "mysqlEntityManagerFactory",
33+
transactionManagerRef = "mysqlTransactionManager"
34+
)
35+
public class MySqlConfig {
36+
37+
@Bean
38+
@Primary
39+
@ConfigurationProperties(prefix = "spring.datasource")
40+
public DataSource mysqlDataSource() {
41+
return DataSourceBuilder.create().build();
42+
}
43+
44+
@Bean(name = "mysqlEntityManagerFactory")
45+
@Primary
46+
public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory() {
47+
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
48+
em.setDataSource(mysqlDataSource());
49+
em.setPackagesToScan(
50+
"com.example.log4u.common",
51+
"com.example.log4u.domain.comment",
52+
"com.example.log4u.domain.diary",
53+
"com.example.log4u.domain.follow",
54+
"com.example.log4u.domain.like",
55+
"com.example.log4u.domain.media",
56+
"com.example.log4u.domain.reports",
57+
"com.example.log4u.domain.supports",
58+
"com.example.log4u.domain.user"
59+
);
60+
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
61+
vendorAdapter.setShowSql(true);
62+
vendorAdapter.setGenerateDdl(true);
63+
em.setJpaVendorAdapter(vendorAdapter);
64+
65+
Map<String, Object> properties = new HashMap<>();
66+
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
67+
properties.put("hibernate.hbm2ddl.auto", "update");
68+
properties.put("hibernate.format_sql", true);
69+
em.setJpaPropertyMap(properties);
70+
71+
return em;
72+
}
73+
74+
@Bean(name = "mysqlTransactionManager")
75+
@Primary
76+
public PlatformTransactionManager mysqlTransactionManager() {
77+
JpaTransactionManager transactionManager = new JpaTransactionManager();
78+
transactionManager.setEntityManagerFactory(mysqlEntityManagerFactory().getObject());
79+
return transactionManager;
80+
}
81+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.example.log4u.common.config;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import javax.sql.DataSource;
7+
8+
import org.springframework.boot.context.properties.ConfigurationProperties;
9+
import org.springframework.boot.jdbc.DataSourceBuilder;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
13+
import org.springframework.orm.jpa.JpaTransactionManager;
14+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
15+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
16+
import org.springframework.transaction.PlatformTransactionManager;
17+
18+
@Configuration
19+
@EnableJpaRepositories(
20+
basePackages = {
21+
"com.example.log4u.domain.map.repository"
22+
},
23+
entityManagerFactoryRef = "postgresqlEntityManagerFactory",
24+
transactionManagerRef = "postgresqlTransactionManager"
25+
)
26+
public class PostgreSqlConfig {
27+
28+
@Bean
29+
@ConfigurationProperties(prefix = "spring.second-datasource")
30+
public DataSource postgresqlDataSource() {
31+
return DataSourceBuilder.create().build();
32+
}
33+
34+
@Bean(name = "postgresqlEntityManagerFactory")
35+
public LocalContainerEntityManagerFactoryBean postgresqlEntityManagerFactory() {
36+
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
37+
em.setDataSource(postgresqlDataSource());
38+
em.setPackagesToScan("com.example.log4u.domain.map.entity");
39+
40+
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
41+
vendorAdapter.setShowSql(true);
42+
vendorAdapter.setGenerateDdl(true);
43+
em.setJpaVendorAdapter(vendorAdapter);
44+
45+
Map<String, Object> properties = new HashMap<>();
46+
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
47+
properties.put("hibernate.hbm2ddl.auto", "none");
48+
properties.put("hibernate.format_sql", true);
49+
em.setJpaPropertyMap(properties);
50+
51+
return em;
52+
}
53+
54+
@Bean(name = "postgresqlTransactionManager")
55+
public PlatformTransactionManager postgresqlTransactionManager() {
56+
JpaTransactionManager transactionManager = new JpaTransactionManager();
57+
transactionManager.setEntityManagerFactory(postgresqlEntityManagerFactory().getObject());
58+
return transactionManager;
59+
}
60+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.example.log4u.common.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.context.annotation.Profile;
6+
7+
import com.querydsl.jpa.impl.JPAQueryFactory;
8+
9+
import jakarta.persistence.EntityManager;
10+
import jakarta.persistence.PersistenceContext;
11+
12+
@Configuration
13+
public class PostgresQuerydslConfig {
14+
15+
@PersistenceContext(unitName = "postgresqlEntityManagerFactory")
16+
private EntityManager postgresEntityManager;
17+
18+
@Bean(name = "postgresJPAQueryFactory")
19+
public JPAQueryFactory postgresJPAQueryFactory() {
20+
return new JPAQueryFactory(postgresEntityManager);
21+
}
22+
}

src/main/java/com/example/log4u/common/config/QueryDslConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.springframework.context.annotation.Bean;
44
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.context.annotation.Primary;
56

67
import com.querydsl.jpa.impl.JPAQueryFactory;
78

@@ -17,6 +18,7 @@ public QueryDslConfig(EntityManager entityManager) {
1718
}
1819

1920
@Bean
21+
@Primary
2022
public JPAQueryFactory jpaQueryFactory() {
2123
return new JPAQueryFactory(entityManager);
2224
}

src/main/java/com/example/log4u/domain/diary/service/DiaryService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
import com.example.log4u.domain.diary.exception.OwnerAccessDeniedException;
2222
import com.example.log4u.domain.diary.repository.DiaryRepository;
2323
import com.example.log4u.domain.follow.repository.FollowRepository;
24+
import com.example.log4u.domain.map.service.MapService;
2425
import com.example.log4u.domain.media.entity.Media;
2526
import com.example.log4u.domain.media.service.MediaService;
26-
import com.example.log4u.domain.user.repository.UserRepository;
2727

2828
import lombok.RequiredArgsConstructor;
2929
import lombok.extern.slf4j.Slf4j;
@@ -34,9 +34,9 @@
3434
public class DiaryService {
3535

3636
private final DiaryRepository diaryRepository;
37-
private final UserRepository userRepository;
3837
private final FollowRepository followRepository;
3938
private final MediaService mediaService;
39+
private final MapService mapService;
4040

4141
// 다이어리 생성
4242
@Transactional
@@ -46,6 +46,7 @@ public void saveDiary(Long userId, DiaryRequestDto request) {
4646
DiaryRequestDto.toEntity(userId, request, thumbnailUrl)
4747
);
4848
mediaService.saveMedia(diary.getDiaryId(), request.mediaList());
49+
mapService.increaseRegionDiaryCount(request.latitude(), request.longitude());
4950
}
5051

5152
// 다이어리 검색
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.example.log4u.domain.map.controller;
2+
3+
import java.util.List;
4+
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.GetMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
import com.example.log4u.domain.map.dto.response.DiaryClusterResponseDto;
12+
import com.example.log4u.domain.map.service.MapService;
13+
14+
import io.swagger.v3.oas.annotations.tags.Tag;
15+
import lombok.RequiredArgsConstructor;
16+
17+
@Tag(name = "지도 API")
18+
@RestController
19+
@RequiredArgsConstructor
20+
@RequestMapping("/maps")
21+
public class MapController {
22+
23+
private final MapService mapService;
24+
25+
@GetMapping("/diaries/cluster")
26+
public ResponseEntity<List<DiaryClusterResponseDto>> getDiaryClusters(
27+
@RequestParam double south,
28+
@RequestParam double north,
29+
@RequestParam double west,
30+
@RequestParam double east,
31+
@RequestParam int zoom
32+
) {
33+
List<DiaryClusterResponseDto> clusters = mapService.getDiaryClusters(south, north, west, east, zoom);
34+
return ResponseEntity.ok(clusters);
35+
}
36+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.example.log4u.domain.map.dto.response;
2+
3+
import com.querydsl.core.annotations.QueryProjection;
4+
5+
public record DiaryClusterResponseDto(
6+
String areaName,
7+
Long areaId,
8+
Double lat,
9+
Double lon,
10+
Long diaryCount
11+
) {
12+
13+
@QueryProjection
14+
public DiaryClusterResponseDto {
15+
}
16+
17+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.example.log4u.domain.map.entity;
2+
3+
import jakarta.persistence.*;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import org.locationtech.jts.geom.Geometry;
7+
8+
@Entity
9+
@Getter
10+
@NoArgsConstructor
11+
@Table(name = "sido_areas", schema = "public")
12+
public class SidoAreas {
13+
14+
@Id
15+
@GeneratedValue(strategy = GenerationType.IDENTITY)
16+
private Long id;
17+
18+
@Column(nullable = false)
19+
private String code;
20+
21+
@Column(nullable = false)
22+
private String name;
23+
24+
@Column(columnDefinition = "geometry")
25+
private Geometry geom;
26+
27+
@Column(columnDefinition = "geometry")
28+
private Geometry center;
29+
30+
@Column(nullable = false)
31+
private Double lat;
32+
33+
@Column(nullable = false)
34+
private Double lon;
35+
}

0 commit comments

Comments
 (0)