Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PostGIS 연동 및 테스트 #24

Merged
merged 5 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions zipsoonapp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ dependencies {
// Development Tools
compileOnly 'org.projectlombok:lombok:1.18.36'
annotationProcessor 'org.projectlombok:lombok:1.18.36'
testCompileOnly 'org.projectlombok:lombok:1.18.36'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.36'
developmentOnly 'org.springframework.boot:spring-boot-devtools:3.4.2'
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.zipsoon.zipsoonapp.config.jackson;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties({"firstPoint", "lastPoint"})
public abstract class PointMixin {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.zipsoon.zipsoonapp.config.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

@MappedTypes(LocalDateTime.class)
public class LocalDateTimeTypeHandler extends BaseTypeHandler<LocalDateTime> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException {
ps.setTimestamp(i, Timestamp.from(parameter.toInstant(ZoneOffset.UTC)));
}

@Override
public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnName);
return timestamp != null ? timestamp.toLocalDateTime() : null;
}

@Override
public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnIndex);
return timestamp != null ? timestamp.toLocalDateTime() : null;
}

@Override
public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Timestamp timestamp = cs.getTimestamp(columnIndex);
return timestamp != null ? timestamp.toLocalDateTime() : null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.zipsoon.zipsoonapp.config.typehandler;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgis.PGgeometry;
import org.postgis.Point;

import java.sql.*;

@MappedTypes(Point.class)
public class PointTypeHandler extends BaseTypeHandler<Point> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Point parameter, JdbcType jdbcType)
throws SQLException {
String pointWkt = String.format("POINT(%f %f)", parameter.getX(), parameter.getY());
ps.setObject(i, pointWkt, Types.OTHER);
}

@Override
public Point getNullableResult(ResultSet rs, String columnName) throws SQLException {
PGgeometry geometry = (PGgeometry) rs.getObject(columnName);
return geometry != null ? convertToPoint(geometry) : null;
}

@Override
public Point getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
PGgeometry geometry = (PGgeometry) rs.getObject(columnIndex);
return geometry != null ? convertToPoint(geometry) : null;
}

@Override
public Point getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
PGgeometry geometry = (PGgeometry) cs.getObject(columnIndex);
return geometry != null ? convertToPoint(geometry) : null;
}

private Point convertToPoint(PGgeometry geometry) {
org.postgis.Point pgPoint = (org.postgis.Point) geometry.getGeometry();
return new Point(pgPoint.x, pgPoint.y);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.zipsoon.zipsoonapp.domain;

public enum PlatformType {
NAVER("네이버부동산");

private final String description;

PlatformType(String description) {
this.description = description;
}

public String getDescription() {
return description;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.zipsoon.zipsoonapp.domain;

import lombok.*;
import org.postgis.Point;

import java.time.LocalDateTime;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Property {
private Long id;
private PlatformType platformType;
private String platformId;
private String articleName;
private String articleStatus;
private String realEstateTypeCode;
private String realEstateTypeName;
private String articleRealEstateTypeCode;
private String articleRealEstateTypeName;
private String tradeTypeCode;
private String tradeTypeName;
private String verificationTypeCode;
private String floorInfo;
private String priceChangeState;
private boolean isPriceModification;
private String price;
private String rentPrc;
private String dealOrWarrantPrc;
private String areaName;
private Double area1;
private Double area2;
private String direction;
private String articleConfirmYmd;
private String representativeImgUrl;
private String articleFeatureDesc;
private String[] tags;
private String buildingName;
private Integer sameAddrCnt;
private Integer sameAddrDirectCnt;
private String sameAddrMaxPrc;
private String sameAddrMinPrc;
private String cpid;
private String cpName;
private String cpPcArticleUrl;
private String cpPcArticleBridgeUrl;
private Boolean cpPcArticleLinkUseAtArticleTitleYn;
private Boolean cpPcArticleLinkUseAtCpNameYn;
private String cpMobileArticleUrl;
private Boolean cpMobileArticleLinkUseAtArticleTitleYn;
private Boolean cpMobileArticleLinkUseAtCpNameYn;
private Boolean isLocationShow;
private String realtorName;
private String realtorId;
private Boolean tradeCheckedByOwner;
private Boolean isDirectTrade;
private Boolean isInterest;
private Boolean isComplex;
private String detailAddress;
private String detailAddressYn;
private String virtualAddressYn;
private Boolean isVrExposed;
private Point location;
private PropertyStatusType status;
private LocalDateTime lastChecked;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
private LocalDateTime deletedAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.zipsoon.zipsoonapp.domain;

public enum PropertyStatusType {
ACTIVE("활성"),
DELETED("삭제됨");

private final String description;

PropertyStatusType(String description) {
this.description = description;
}

public String getDescription() {
return description;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.zipsoon.zipsoonapp.repository;

import com.zipsoon.zipsoonapp.domain.Property;
import com.zipsoon.zipsoonapp.repository.mapper.PropertyMapper;
import lombok.RequiredArgsConstructor;
import org.postgis.Point;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@RequiredArgsConstructor
public class PropertyRepository {
private final PropertyMapper propertyMapper;

public List<Property> findPropertiesWithinDistance(Point coord, int radius) {
return propertyMapper.findPropertiesWithinDistance(coord, radius);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.zipsoon.zipsoonapp.repository.mapper;

import com.zipsoon.zipsoonapp.domain.Property;
import org.apache.ibatis.annotations.Mapper;
import org.postgis.Point;

import java.util.List;

@Mapper
public interface PropertyMapper {
List<Property> findPropertiesWithinDistance(Point coord, int radius);
}
6 changes: 4 additions & 2 deletions zipsoonapp/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/testdbapp
url: jdbc:postgresql://localhost:5432/testdbbatch
username: postgres
password: postgres

mybatis:
mapper-locations: classpath:mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
map-underscore-to-camel-case: true
type-handlers-package: com.zipsoon.zipsoonapp.config.typehandler
# type-aliases-package: com.zipsoon.zipsoonapp.domain
21 changes: 21 additions & 0 deletions zipsoonapp/src/main/resources/mapper/PropertyMapper.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zipsoon.zipsoonapp.repository.mapper.PropertyMapper">
<select id="findPropertiesWithinDistance" resultType="com.zipsoon.zipsoonapp.domain.Property">
SELECT
p.*,
ST_Distance(
p.location::geography,
ST_SetSRID(ST_MakePoint(#{coord.x}, #{coord.y}), 4326)::geography
) as distance
FROM property p
WHERE ST_DWithin(
p.location::geography,
ST_SetSRID(ST_MakePoint(#{coord.x}, #{coord.y}), 4326)::geography,
#{radius}
)
ORDER BY distance
</select>
</mapper>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.zipsoon.zipsoonapp;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.zipsoon.zipsoonapp.config.jackson.PointMixin;
import com.zipsoon.zipsoonapp.domain.Property;
import com.zipsoon.zipsoonapp.repository.mapper.PropertyMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.postgis.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@Slf4j
@SpringBootTest
class PostGISConfigurationTest {
@Autowired
private PropertyMapper propertyMapper;

private final ObjectMapper objectMapper = new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT)
.addMixIn(org.postgis.Point.class, PointMixin.class)
.registerModule(new JavaTimeModule());

@Test
void shouldHandleGeometryType() throws JsonProcessingException {
Point coord = new Point(126.96, 37.572); // 독립문역 사거리
int radius = 100; // 미터

List<Property> properties = propertyMapper.findPropertiesWithinDistance(coord, radius);

String prettyJson = objectMapper.writeValueAsString(properties);
log.info("Properties within {}m of ({}, {}): total {} found\n{}", radius, coord.getX(), coord.getY(), properties.size(), prettyJson);

assertThat(properties).isNotNull();
}
}
Loading