かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Grooy スクリプトをそのまま渡して実行する Spring Boot+Picocli ベースのコマンドラインアプリを作成する ( その4 )( テーブルのデータを CSV フォーマットで出力する Groovy スクリプトを作成する )

概要

記事一覧はこちらです。

Grooy スクリプトをそのまま渡して実行する Spring Boot+Picocli ベースのコマンドラインアプリを作成する ( その3 )( サンプルの Groovy スクリプトをプロジェクト内に置く+PostgreSQL、MySQL を起動するための docker-compose.yml を作成してデータベース・テーブルを作成する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • PostgreSQL の sampledb の publications テーブルのデータを CSV フォーマットで出力する Groovy スクリプトを作成します。

参照したサイト・書籍

  1. Connecting to an Amazon Aurora DB cluster
    https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Connecting.html

  2. Dependency management with Grape
    http://docs.groovy-lang.org/latest/html/documentation/grape.html

  3. Groovy - File I/O
    https://www.tutorialspoint.com/groovy/groovy_file_io.htm

目次

  1. groovy-script-executor.jar に PostgreSQL、MariaDB の JDBC Driver を入れる
  2. PostgreSQL の sampledb の publications テーブルのデータを CSV フォーマットで出力する
    1. 標準出力にカンマ区切りで出力する
    2. ファイルにカンマ区切りで出力する
    3. univocity-parsers を使用してファイルに出力する
  3. groovy-script-executor.jar 内に作成したクラスを Groovy スクリプトから呼び出せるのか?

手順

groovy-script-executor.jar に PostgreSQLMariaDBJDBC Driver を入れる

JDBC Driver は @GrabDependency management with Grape 参照)で指定するのではなく groovy-script-executor.jar に入れます。

build.gradle を以下のように変更します。

dependencies {
    def postgresqlJdbcDriver = "org.postgresql:postgresql:42.3.1"
    def mariadbJdbcDriver = "org.mariadb.jdbc:mariadb-java-client:2.7.4"
    def groovyVersion = "3.0.9"
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの
    runtimeOnly("${postgresqlJdbcDriver}")
    runtimeOnly("${mariadbJdbcDriver}")
    implementation("com.univocity:univocity-parsers:2.9.1")
    ..........
  • dependencies block に以下の行を追加します。
    • def postgresqlJdbcDriver = "org.postgresql:postgresql:42.3.1"
    • def mariadbJdbcDriver = "org.mariadb.jdbc:mariadb-java-client:2.7.4"
    • runtimeOnly("${postgresqlJdbcDriver}")
    • runtimeOnly("${mariadbJdbcDriver}")

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

build タスクを実行し、生成した groovy-script-executor.jar を D:\tmp にコピーします。

PostgreSQL の sampledb の publications テーブルのデータを CSV フォーマットで出力する

標準出力にカンマ区切りで出力する

groovy-script-executor/src/main/groovy/sample の下に PublicationsTableToSystemOutInCSV.groovy を新規作成し、以下のコードを記述します。

  • Windows のコンソールに出力するので、出力時の文字コードwindows-31j を指定しています。
  • isbm は NULL のデータが存在し、そのままでは NULL と出力されるため、coalesce 関数で NULL の場合には空文字列を取得するようにしています。
  • select 文を実行するのに sql.query(...) { resultSet -> }sql.eachRow(...) { row -> } のメソッドも存在しますが、row.values().join(",") が使用したいので sql.rows(...) メソッドを使用しています。
package sample

import groovy.sql.Sql

class PublicationsTableToSystemOutInCSV {

    static void main(args) {
        def sql = Sql.newInstance("jdbc:postgresql://localhost:5432/sampledb",
                "sampledb_user",
                "xxxxxxxx",
                "org.postgresql.Driver")

        try (Writer writer = System.out.newWriter("windows-31j")) {
            def rows = sql.rows("""\
                select coalesce(isbm, ''),
                       title_author
                from publications
            """)
            rows.each { row ->
                writer.println(row.values().join(","))
            }
        }

        sql.close()
    }

}

PublicationsTableToSystemOutInCSV.groovy を D:\tmp にコピーし gse PublicationsTableToSystemOutInCSV.groovy を実行すると取得したデータが出力されます。

f:id:ksby:20211103100036p:plain

ファイルにカンマ区切りで出力する

groovy-script-executor/src/main/groovy/sample の下に PublicationsTableToFileInCSV.groovy を新規作成し、以下のコードを記述します。

package sample

import groovy.sql.Sql

class PublicationsTableToFileInCSV {

    static void main(String[] args) {
        def sql = Sql.newInstance("jdbc:postgresql://localhost:5432/sampledb",
                "sampledb_user",
                "xxxxxxxx",
                "org.postgresql.Driver")

        new File("publications.csv").withWriter { writer ->
            def rows = sql.rows("""\
                select coalesce(isbm, ''),
                       title_author
                from publications
            """)
            rows.each { row ->
                writer.println(row.values().join(","))
            }
        }

        sql.close()
    }

}

PublicationsTableToFileInCSV.groovy を D:\tmp にコピーし gse PublicationsTableToFileInCSV.groovy を実行すると取得したデータがファイルに出力されます。

f:id:ksby:20211103113754p:plain

univocity-parsers を使用してファイルに出力する

groovy-script-executor/src/main/groovy/sample の下に PublicationsTableToFileUsingUnivocityParsers.groovy を新規作成し、以下のコードを記述します。

package sample

import com.univocity.parsers.annotations.Parsed
import com.univocity.parsers.common.processor.BeanWriterProcessor
import com.univocity.parsers.csv.CsvWriter
import com.univocity.parsers.csv.CsvWriterSettings
import groovy.sql.Sql

class PublicationsTableToFileUsingUnivocityParsers {

    static class CsvRecord {
        @Parsed(index = 0, field = "isbm")
        String isbm
        @Parsed(index = 1, field = "title_author")
        String title_author
    }

    static void main(args) {
        def sql = Sql.newInstance("jdbc:postgresql://localhost:5432/sampledb",
                "sampledb_user",
                "xxxxxxxx",
                "org.postgresql.Driver")

        CsvWriterSettings settings = new CsvWriterSettings()
        settings.setQuoteAllFields(true)
        BeanWriterProcessor<CsvRecord> writerProcessor = new BeanWriterProcessor<>(CsvRecord)
        settings.setRowWriterProcessor(writerProcessor)
        CsvWriter writer = new CsvWriter(new File("publications.csv"), settings)

        writer.writeHeaders()

        CsvRecord publications = new CsvRecord()
        sql.eachRow("select * from publications") { row ->
            publications.isbm = row.isbm
            publications.title_author = row.title_author
            writer.processRecord(publications)
        }

        writer.close()
        sql.close()
    }

}

PublicationsTableToFileInCSV.groovy を D:\tmp にコピーし gse PublicationsTableToFileUsingUnivocityParsers.groovy を実行すると取得したデータがファイルに出力されます。

f:id:ksby:20211103115600p:plain

groovy-script-executor.jar 内に入れている univocity-parsers のモジュールを問題なく呼び出すことが出来ています。

groovy-script-executor.jar 内に作成したクラスを Groovy スクリプトから呼び出せるのか?

groovy-script-executor.jar 内に共通ライブラリとして利用するクラスを作成して Groovy スクリプトから呼び出せるのか試してみます。

groovy-script-executor/src/main/groovy の下に ksby.util パッケージを作成し、その下に DbUtils.groovy を作成して以下のコードを記述します。

package ksby.util

import groovy.sql.Sql

class DbUtils {

    static Sql connectSampleDb() {
        return Sql.newInstance("jdbc:postgresql://localhost:5432/sampledb",
                "sampledb_user",
                "xxxxxxxx",
                "org.postgresql.Driver")
    }

}

groovy-script-executor/src/main/groovy/sample/PublicationsTableToSystemOutInCSV.groovy の DB への接続処理を Sql.newInstance(...)DbUtils.connectSampleDb() に変更します。

package sample

import ksby.util.DbUtils

class PublicationsTableToSystemOutInCSV {

    static void main(args) {
        def sql = DbUtils.connectSampleDb()

        try (Writer writer = System.out.newWriter("windows-31j")) {
            def rows = sql.rows("""\
                select coalesce(isbm, ''),
                       title_author
                from publications
            """)
            rows.each { row ->
                writer.println(row.values().join(","))
            }
        }

        sql.close()
    }

}

build タスクを実行して生成された groovy-script-executor.jar と PublicationsTableToSystemOutInCSV.groovy を D:\tmp へコピーした後、gse PublicationsTableToSystemOutInCSV.groovy を実行すると取得したデータが出力されました。

f:id:ksby:20211103213649p:plain

groovy-script-executor.jar 内に入っているクラスを Groovy スクリプトから問題なく呼び出すことが出来ました。

履歴

2021/11/03
初版発行。