■ はじめに
SparkからSnowflakeへの接続について考える
https://dk521123.hatenablog.com/entry/2023/03/19/013833
で、JDBCでもSnowflakeにアクセスすることに触れたが 今回は、ScalaでJDBCドライバからDBにアクセスすることについて触れる
目次
【1】JDBCドライバ取得 1)PostgreSQL 2)Snowflake 【2】JDBC ドライバー 1)JDBC ドライバークラス 2)JDBC ドライバー接続文字列 【3】API 1)PostgreSQL 2)Snowflake 【4】サンプル 1)PostgreSQL
【1】JDBCドライバ取得
1)PostgreSQL
libraryDependencies ++= Seq( "org.postgresql" % "postgresql" % "42.6.0",
https://mvnrepository.com/artifact/org.postgresql/postgresql
2)Snowflake
libraryDependencies ++= Seq( "net.snowflake" % "snowflake-jdbc" % "3.13.28",
https://mvnrepository.com/artifact/net.snowflake/snowflake-jdbc
https://docs.snowflake.com/ja/user-guide/jdbc-download#integrating-the-driver-into-a-maven-project
【2】JDBC ドライバー
1)JDBC ドライバークラス
[1] PostgreSQL
Class.forName("org.postgresql.Driver")
[2] Snowflake
Class.forName("net.snowflake.client.jdbc.SnowflakeDriver")
https://docs.snowflake.com/ja/user-guide/jdbc-configure#jdbc-driver-class
https://docs.snowflake.com/ja/user-guide/jdbc-api#object-driver
2)JDBC ドライバー接続文字列
[1] PostgreSQL
// jdbc:postgresql://<host>:<port>/<db_name>?<connection_params> val connectionURL ="jdbc:postgresql://localhost:5432/sample_db"
[2] Snowflake
// Syntax // jdbc:snowflake://<account_identifier>.snowflakecomputing.com/?<connection_params> val connectionURL = "jdbc:snowflake://myorganization-myaccount.snowflakecomputing.com/?query_tag='folder%3Dfolder1%20folder2%26'
https://docs.snowflake.com/ja/user-guide/jdbc-configure#jdbc-driver-connection-string
【3】API
1)PostgreSQL
https://www.postgresql.jp/document/7.4/html/jdbc.html
2)Snowflake
* メソッドの中には、Snowflake独自の動きをするメソッドも ちらほらあるので使う前に確認しておいた方がよさそう
オブジェクト: Statement
https://docs.snowflake.com/ja/user-guide/jdbc-api#object-statement
オブジェクト: PreparedStatement
https://docs.snowflake.com/ja/user-guide/jdbc-api#object-preparedstatement
【4】サンプル
1)PostgreSQL
例1:SELECT文
import java.sql.DriverManager import java.sql.Connection object Hello { def main(args: Array[String]) { val dbUrl = "jdbc:postgresql://localhost:5432/sample_db" val dbUser = "postgres" val dbPassword = "password" var dbConnector: Connection = null Class.forName("org.postgresql.Driver") try { dbConnector = DriverManager.getConnection(dbUrl, dbUser, dbPassword) val sql = "SELECT user_id, user_name, created_at FROM users LIMIT ?" val limit = 5 val sqlStatement = dbConnector.prepareStatement(sql) sqlStatement.setInt(1, limit) val resultSet = sqlStatement.executeQuery() var index = 0 while (resultSet.next()) { println(s"*[${index}]******************") println("user_id: " + resultSet.getInt(1)) println("user_name: " + resultSet.getString("user_name")) println("created_at: " + resultSet.getTimestamp("created_at")) println("*******************") index = index + 1 } resultSet.close() sqlStatement.close() } finally { if (dbConnector != null) { dbConnector.close() } } println("Done...") } }
サンプルデータ
CREATE TABLE IF NOT EXISTS "users" ( "user_id" INTEGER NOT NULL, "user_name" VARCHAR(50) NOT NULL, "created_at" TIMESTAMP NULL DEFAULT 'CURRENT_TIMESTAMP', PRIMARY KEY ("user_id") ); INSERT INTO "users" ("user_id", "user_name", "created_at") VALUES (1, 'Mike', '2019-12-19 21:50:21.3885'), (2, 'Tom', '2019-12-19 21:50:21.3885'), (3, 'Sam', '2019-12-19 21:50:21.3885'), (4, 'Kevin', '2019-12-19 21:50:27.483248'), (5, 'Smith', '2019-12-19 21:50:27.484514'), (6, 'Ken', '2019-12-19 21:50:27.484514'), (10, 'Sam', '2020-08-26 22:39:55.175736'), (12, 'Naomi', '2020-08-26 22:39:55.175736'), (20, 'Tim', '2021-08-02 16:39:55.175736'), (30, 'kevin', '2021-08-02 16:40:55.175736');
例2:複数SQL文実行 / addBatch
import java.sql.DriverManager import java.sql.Connection object Hello { def main(args: Array[String]) { val dbUrl = "jdbc:postgresql://localhost:5432/sample_db" val dbUser = "postgres" val dbPassword = "password" var dbConnector: Connection = null Class.forName("org.postgresql.Driver") try { dbConnector = DriverManager.getConnection(dbUrl, dbUser, dbPassword) val statement = dbConnector.createStatement() statement.addBatch("/*ex1*/ DROP TABLE IF EXISTS test;") statement.addBatch("/*ex2*/ CREATE TABLE test(id integer, name varchar);") statement.addBatch("/*ex3*/ INSERT INTO test VALUES(1, 'Mike');") statement.addBatch("/*ex4*/ INSERT INTO test VALUES(2, 'Smith');") val results = statement.executeBatch() println(s"Result ${results.length}") statement.close() } finally { if (dbConnector != null) { dbConnector.close() } } println("Done...") } }
例3:複数SQL文実行 / execute
import java.sql.DriverManager import java.sql.Connection object Hello { def main(args: Array[String]) { val dbUrl = "jdbc:postgresql://localhost:5432/sample_db" val dbUser = "postgres" val dbPassword = "password" var dbConnector: Connection = null Class.forName("org.postgresql.Driver") try { dbConnector = DriverManager.getConnection(dbUrl, dbUser, dbPassword) val statement = dbConnector.createStatement() val param11 = 1 val param12 = "Mike" val param21 = 2 val param22 = "Kevin" val sql = s""" -- ex1 DROP TABLE IF EXISTS test2; -- ex2 CREATE TABLE test2 ( id integer, name varchar ); -- ex3 INSERT INTO test2 VALUES(${param11}, '${param12}'); INSERT INTO test2 VALUES(${param21}, '${param22}'); INSERT INTO test2 VALUES(3, 'Tommy'); """ val isOk = statement.execute(sql) println(s"Result ${isOk}") statement.close() } finally { if (dbConnector != null) { dbConnector.close() } } println("Done...") } }
関連記事
Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805
Scala ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/12/184331
Scala ~ 基本編 / 繰り返し ~
https://dk521123.hatenablog.com/entry/2023/01/24/000000
Scala ~ 基本編 / Option型 ~
https://dk521123.hatenablog.com/entry/2023/03/09/000000
Scala ~ 基本編 / メソッド ~
https://dk521123.hatenablog.com/entry/2023/03/03/000000
Scala ~ 基本編 / クラス ~
https://dk521123.hatenablog.com/entry/2023/03/14/000857
Scala ~ 基本編 / コレクション ~
https://dk521123.hatenablog.com/entry/2023/03/13/000345
Scala ~ 基本編 / 日付・日時 ~
https://dk521123.hatenablog.com/entry/2023/03/08/000000
Scala ~ 基本編 / 正規表現 ~
https://dk521123.hatenablog.com/entry/2023/03/18/034704
Scala ~ 基本編 / ジェネリック
https://dk521123.hatenablog.com/entry/2023/03/21/003817
Scala ~ Enum ~
https://dk521123.hatenablog.com/entry/2023/01/05/000000
Scala ~ ファイル名・パスの扱い ~
https://dk521123.hatenablog.com/entry/2023/03/11/000000
Scala ~ ファイルハンドリング ~
https://dk521123.hatenablog.com/entry/2023/01/03/000000
Scala ~ YAML ~
https://dk521123.hatenablog.com/entry/2023/03/16/012034
Scala ~ AWS SDK ~
https://dk521123.hatenablog.com/entry/2023/03/24/211033
SBT ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/22/000000
SBT ~ 基本編 / build.sbt ~
https://dk521123.hatenablog.com/entry/2023/01/27/000000
SBT ~ 基本編 / sbtコマンド ~
https://dk521123.hatenablog.com/entry/2023/01/26/000000
SBT ~ sbtプラグイン ~
https://dk521123.hatenablog.com/entry/2023/01/25/000000
JavaでEmail ~ JavaMail / Text ~
https://dk521123.hatenablog.com/entry/2016/07/16/222422
JavaでEmail ~ JavaMail / 添付ファイル ~
https://dk521123.hatenablog.com/entry/2016/07/17/023459
JavaでEmail ~ SMTP認証 ~
https://dk521123.hatenablog.com/entry/2016/11/07/215251
JavaでEmail ~ SMTP認証 / DIGEST-MD5 ~
https://dk521123.hatenablog.com/entry/2016/12/07/222229
JavaでEmail ~ JavaMail / TLS ~
https://dk521123.hatenablog.com/entry/2017/05/03/163219
JavaでEmail ~ JavaMail / Return-Path・Errors-To ~
https://dk521123.hatenablog.com/entry/2017/05/07/000344
Amazon SES ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2017/04/28/234103
Amazon S3 ~ Boto3編 ~
https://dk521123.hatenablog.com/entry/2019/10/21/230004
Amazon S3 ~ Boto3でファイル存在チェック ~
https://dk521123.hatenablog.com/entry/2022/02/26/182526
AWS Glue ~ Scalaでの実装 ~
https://dk521123.hatenablog.com/entry/2023/03/17/000000
AWS Glue ~ ローカル環境を作成する / Glue v3.0版 ~
https://dk521123.hatenablog.com/entry/2022/01/31/165650
LocalStack ~ ローカルで疑似AWSを作成する ~
https://dk521123.hatenablog.com/entry/2019/12/14/010524
LocalStack ~ ローカルで疑似Lambda/S3/DynamoDBを作成する ~
https://dk521123.hatenablog.com/entry/2019/12/16/231149
SparkからSnowflakeへの接続について考える
https://dk521123.hatenablog.com/entry/2023/03/19/013833