java.lang.ClassNotFoundException: org.postgresql.Driver
java.sql.SQLException: No suitable driver
앞의 것은 jar 가 클래스패스에 없다는 뜻이다. 뒤의 것은 등록된 드라이버 중 그 URL 을 처리하겠다고 나서는 것이 없다는 뜻으로, 원인이 셋이다. jar 가 없거나, URL 접두사가 틀렸거나, 서비스 로더가 드라이버를 발견하지 못한 것이다.
| 대상 | URL | 드라이버 클래스 |
|---|---|---|
| PostgreSQL | jdbc:postgresql://host:5432/db |
org.postgresql.Driver |
| MySQL | jdbc:mysql://host:3306/db |
com.mysql.cj.jdbc.Driver |
| MariaDB | jdbc:mariadb://host:3306/db |
org.mariadb.jdbc.Driver |
| Oracle | jdbc:oracle:thin:@//host:1521/SERVICE |
oracle.jdbc.OracleDriver |
| SQL Server | jdbc:sqlserver://host:1433;databaseName=db |
com.microsoft.sqlserver.jdbc.SQLServerDriver |
| Sybase (jConnect) | jdbc:sybase:Tds:host:5000/db |
com.sybase.jdbc4.jdbc.SybDriver |
| Db2 | jdbc:db2://host:50000/db |
com.ibm.db2.jcc.DB2Driver |
Sqoop 이나 다른 도구에서 대상 DB 는 Sybase 인데 오류에 Oracle 드라이버 이름이 보인다면, 설정에 남아 있는 다른 커넥션의 드라이버 클래스를 그대로 쓰고 있는 것이다. --driver 인자와 URL 접두사가 같은 제품을 가리키는지 확인한다.
도구마다 클래스패스를 구성하는 방식이 다르다. 라이브러리 디렉터리에 두는 것이 가장 확실하다.
wget -P /opt/jdbc https://jdbc.postgresql.org/download/postgresql-42.7.9.jar
cp /opt/jdbc/postgresql-42.7.9.jar "$HIVE_HOME/lib/"
Hive Metastore 는 기동 시점에 클래스패스를 구성하므로 hive-site.xml 의 hive.aux.jars.path 만으로는 늦는 경우가 있다. 메타스토어가 No suitable driver 로 죽는다면 $HIVE_HOME/lib 에 직접 넣거나 환경 변수로 준다.
export HIVE_AUX_JARS_PATH=/opt/jdbc/postgresql-42.7.9.jar
export METASTORE_CLASSPATH=/opt/jdbc/postgresql-42.7.9.jar
<property>
<name>hive.aux.jars.path</name>
<value>file:///opt/jdbc/postgresql-42.7.9.jar</value>
</property>
file:// 접두사를 붙이고, 여러 개면 쉼표로 잇는다. HiveServer2 와 Metastore 는 별개 프로세스이므로 양쪽 모두 볼 수 있어야 한다.
Sqoop 은 $SQOOP_HOME/lib 또는 --libjars 를 쓴다. 일반 자바 애플리케이션은 -cp 에 디렉터리 와일드카드를 준다.
java -cp "app.jar:/opt/jdbc/*" com.example.Main
JDBC 4.0(Java 6) 부터 jar 안의 META-INF/services/java.sql.Driver 를 보고 자동 등록한다. 다음 코드는 이제 필요 없다.
Class.forName("org.postgresql.Driver");
다만 셰이딩된 uber jar 를 만들 때 이 서비스 파일이 병합되지 않으면 자동 등록이 깨진다. Maven Shade 플러그인이라면 ServicesResourceTransformer 를 넣는다. 이 상황에서만 Class.forName 이 우회책이 된다.
java.sql.DriverManager.drivers().forEach(d -> System.out.println(d.getClass().getName()));
unzip -l postgresql-42.7.9.jar | grep -i 'META-INF/services'
드라이버 문제가 풀리면 다음 단계의 오류가 나온다. 진전이 있다는 뜻이다.
MetaException(message:Version information not found in metastore.)
접속은 됐지만 메타스토어 스키마가 아직 만들어지지 않은 것이다.
schematool -dbType postgres -initSchema
schematool -dbType postgres -info
이미 스키마가 있는데 버전 정보만 없다면 -initSchema 는 기존 테이블과 충돌한다. -upgradeSchema 또는 버전 확인을 먼저 한다. 운영 메타스토어에는 반드시 백업을 받고 실행한다.