Springboot PostGIS 적용하기

prana·2024년 7월 8일
0

오류-문제해결

목록 보기
3/15
post-thumbnail
# application.yml
spring:
  config:
    activate.on-profile: local
    import: optional:file:.env.local[.properties]
  datasource:
    url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
    username: ${DB_USER}
    password: ${DB_PASSWORD}
    driver-class-name: org.postgresql.Driver
  jpa:
    generate-ddl: true
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect

logging:
  level:
    root: INFO
    org.springframework.web: DEBUG
    org.hibernate: DEBUG
  • 참고로, dialect 부분 지우고
database-platform: org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect

이걸로 해도 무방하다.

spring:
  config:
    activate.on-profile: local
    import: optional:file:.env.local[.properties]
  datasource:
    url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
    username: ${DB_USER}
    password: ${DB_PASSWORD}
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true
    format_sql: true
    database-platform: org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
#    properties:
#      hibernate:
#        dialect: org.hibernate.dialect.PostgreSQLDialect

logging:
  level:
    root: INFO
    org.springframework.web: DEBUG
    org.hibernate: DEBUG

문제

  • 여기에서 dialect 부분에서 오류가 심하게 났었다.
org.springframework.dao.DataIntegrityViolationException: could not execute statement [Data conversion error converting "X'010100000050fc1873d79a5ec0d0d556ec2fe34240' (ROAD: ""POINT"" GEOMETRY(POINT, 4326) NOT NULL)"; SQL statement:
insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default) [22018-224]] [insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default)]; SQL [insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default)]

그 이유는? create문으로 extension을 설치하지 않았고 그에 따라 jpa에 정의된 테이블도 생성되지 않았었다.

CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;

# 설치 확인용
# SELECT * FROM pg_extension WHERE extname = 'postgis';
# SELECT * FROM pg_extension WHERE extname = 'postgis_topology';
  • create문을 직접 넣어줘야 그제서야 문제 없다는 것을 확인했다.
    근데 이걸 매번 직접 넣는게 번거롭다보니..

해결

  • 그 전에 우리가 해야 할 것이 있다.

    docker desktop에서

    • 컨테이너 지우기
    • 이미지 지우기
    • 볼륨 지우기

  • 디렉토리 구조는 다음과 같다.

  • Dockerfile에 작성하기 전에, init-db.sh파일을 만들어서 스크립트를 만들고, dockerfile에 설정할 수 있게 경로를 넣어주었다.

  • Dockerfile

# 기본 이미지로 PostgreSQL 16을 사용
FROM postgres:16

# 필요한 패키지 설치
RUN apt-get update && \
    apt-get install -y postgis postgresql-16-postgis-3

# 기본 설정 및 확장 설치
RUN mkdir -p /docker-entrypoint-initdb.d
COPY ./init-db.sh /docker-entrypoint-initdb.d/

# 스크립트 파일 권한 설정
RUN chmod +x /docker-entrypoint-initdb.d/init-db.sh
  • init-db.sh
#!/bin/bash
set -e

# Connect to the default database and create the PostGIS extension
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE EXTENSION IF NOT EXISTS postgis;
    CREATE EXTENSION IF NOT EXISTS postgis_topology;
EOSQL
  • docker-compose.local.yml
version: '3.8'
services:
  db:
    build:
      context: .
      dockerfile: Dockerfile
    hostname: localhost
    container_name: postgres-container
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    ports:
      - "5432:5432"
    env_file:
      - .env.local
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:latest
    container_name: redis-container
    ports:
      - "6379:6379"

volumes:
  postgres-data:
  • env_file을 참조할 수 있게 해주었다. 이렇게 쓰는구나를 배웠다.
  • .env.local
DB_HOST=localhost
DB_PORT=5432
DB_NAME=test_db
DB_USER=비밀
DB_PASSWORD=비밀
  • 도커 컨테이너 다 중지, 볼륨지우고, 이미지도 다 지우고, 다시 명령어 실행하면
docker-compose -f docker-compose.local.yml --env-file .env.local up -d --build

  • postgis 익스텐션 설치가 완료되면서, 스키마들이 추가된 것들을 확인할 수 있다.

Point 타입 저장 성공!

문제의 연속

  • 일단, postgis를 설치하고 Test클래스에서 test 메서드 시도하면, 저장이 안 된다!
org.springframework.dao.DataIntegrityViolationException: could not execute statement [Data conversion error converting "X'010100000050fc1873d79a5ec0d0d556ec2fe34240' (ROAD: ""POINT"" GEOMETRY(POINT, 4326) NOT NULL)"; SQL statement:
insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default) [22018-224]] [insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default)]; SQL [insert into road (address,content,created_at,point,updated_at,id) values (?,?,?,?,?,default)]

궁금증

  • application-test.yml이거를 따로 만들면, 이건 어떻게 실행이 되는 걸까?

  • 새벽 4시반까지 팀원 한 분과 함께 고군분투하면서.. 많이 배울 수 있었다. 이제 진도 빼야해서 부지런히 해야한다. 힘내잣

0개의 댓글