Development/Spring

[JPA] JPA MySQL 몇 가지 이슈에 대해서,,, GenericJDBCException

hyelie 2022. 10. 4. 15:00

1. JPA는 맞게 짠 것 같은데 JPA가 안돌아 가는 경우.

could not execute statement; nested exception is org.hibernate.exception.
org.springframework.orm.jpa.JpaSystemException:
could not execute statement; nested exception is org.hibernate.exception.GenericJDBCException: could not execute

 

이런 에러가 뜨는 경우 - JPA, 즉 Spring에서 설정한 언어(UTF-8)과 mysql의 언어 셋, charset이 달라서 그렇다. 나는 docker로 mysql을 설치했다. 그런데 여기서

 

MySQL에서 아래 명령어를 쳐보자.

status;
SHOW FULL COLUMNS FROM $TABLE명;

status를 쳐서 나오는 명령어다. server, db characterset이 서버 측, schema를 만들 때 기본으로 쓰는 charset이고, client, conn.이 client가 접속할 때, connection에서 사용할 때 언어를 사용하는 것이다.

 

근데 docker에서 mysql을 설치하면 위 4개 명령어가 전부 latin1으로 설정되어 있다... 그래서 spring은 utf8로 입력하지만 mysql은 latin1을 저장하기 때문에 sql을 실행할 수 없다는 글이 나오는 거다..ㅋㅋㅋㅋ진짜 화가 난다.

 

해결법은, docker에서 mysql을 설치할 때 값을 바꾸어 주면 된다. 그리고 spring의 application.properties도 utf-8을 사용하게 해야 한다.

 

이전 게시글에서는 다 바꿔 두었지만 분명히 까먹을 게 분명하기에 따로 메모해 둔다.

 

 

> local/docker-compose.yml

version: "3"

services:
    mysql:
        image: mysql:5.6
        environment:
            MYSQL_DATABASE: bizschema
            MYSQL_ROOT_PASSWORD: rootpw
            MYSQL_USER: devroot
            MYSQL_PASSWORD: devpw
            LANG: C.UTF-8
        volumes:
            - local-mysqlvol:/var/lib/mysql
        ports:
            - 3306:3306
        command:  --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
        container_name: local-mysql


volumes:
    local-mysqlvol:

 

> ci-server/docker-compose.yml

version: "3"

services:
    jenkins:
        container_name: jenkins-compose
        image: jenkins/jenkins:lts
        user: root       
        ports:
         - "8081:8080" 
        volumes:
         - /var/run/docker.sock:/var/run/docker.sock
         - /usr/bin/docker:/usr/bin/docker
         - jenkins_data:/var/jenkins_home
        networks:
         - backend-network

    sonarqube:
        image: sonarqube:lts
        container_name: sonarqube
        ports:
         - "9000:9000"
        volumes:
         - sonarqube_conf:/opt/sonarqube/conf
         - sonarqube_data:/opt/sonarqube/data
         - sonarqube_extensions:/opt/sonarqube/extensions
         - sonarqube_logs:/opt/sonarqube/logs

    mysql:
        image: mysql:5.6
        container_name: ci-mysql
        environment: 
            MYSQL_DATABASE: bizschema
            MYSQL_ROOT_PASSWORD: rootpw
            MYSQL_USER: devroot
            MYSQL_PASSWORD: devpw
            LANG: C.UTF-8
        ports:
         - "3306:3306"
        command:  --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
        volumes:
         - ciserver-mysqlvol:/var/lib/mysql
        networks:
         - backend-network
        
        
volumes:
    ciserver-mysqlvol:
    jenkins_data:
    sonarqube_conf:
    sonarqube_data:
    sonarqube_extensions:
    sonarqube_logs:

networks:
    backend-network:

docker에서 mysql을 올릴 때 language를 설정해 준다.

 

 

> kubernetes cluster/mysql-deploy.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
spec:
  selector:
    matchLabels:
      app: mysql
      tier: backend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mysql
        tier: backend
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-root-pw
                key: rootpw
          - name: MYSQL_DATABASE
            valueFrom:
              secretKeyRef:
                name: dbinfo
                key: dbname
          - name: MYSQL_USER
            valueFrom:
              secretKeyRef:
                name: userinfo
                key: username
          - name: MYSQL_PASSWORD
            valueFrom:
              secretKeyRef:
                name: userinfo
                key: userpw
          - name: LANG
            value: C.UTF-8
        ports:
          - containerPort: 3306
            name: mysql
        args:
        - --character-set-server=utf8mb4
        - --collation-server=utf8mb4_general_ci
        volumeMounts:
          - name: mysql-persistent-storage
            mountPath: /var/lib/mysql
      volumes:
        - name: mysql-persistent-storage
          persistentVolumeClaim:
            claimName: mysql-pvc


# mysql-root-pw : rootpw
# kubectl create secret generic mysql-root-pw --from-literal=rootpw=root

# userinfo: username, userpw
# kubectl create secret generic userinfo --from-literal=username='depuser' --from-literal=userpw='depuserpw'

# dbinfo : dbname, url
# kubectl create secret generic dbinfo --from-literal=dbname=bizschema --from-literal=url='jdbc:mysql://35.184.171.248:3306/bizschema?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnectForPools=true&serverTimezone=UTC'

# kubectl get secrets

kubernetes에서 mysql을 올릴 때도 lang, args를 설정해 준다.

 

 

> spring/application.properties

spring.config.activate.on-profile=common
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.config.activate.on-profile=localdb
spring.datasource.url=jdbc:mysql://localhost:3306/bizschema?autoReconnect=true&useSSL=false&autoReconnectForPools=true&serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=devroot
spring.datasource.password=devpw

application.properties는 datasource url에 useUnicode, characterEncoding을 설정해 주어야 한다.