[JPA] JPA MySQL 몇 가지 이슈에 대해서,,, GenericJDBCException
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을 설정해 주어야 한다.