GCS(Google Cloud Storage)に配置したファイルを、SQL Server搭載済の仮想マシンに転送し、SQL Serverにデータロードし、データロードしたデータを利用してデータ分析用のデータ(ディメンション・キューブ)であるSSASプロジェクトを、SQL Server Analysis Serverに配置するところまで、一括で実施できるJavaプログラムを作成したため、その内容について共有する。
今回は、Javaプログラムのソースコードについて述べる。
下記記事のように、Mavenプロジェクトを作成している。
JavaでSQL Serverにデータロードするプログラムを作成した(ソースコード編)今回も引き続き、Javaで作成したSQL Serverにデータロードするプログラムについて記載する。ここでは、JavaでSQL Serv...
また、pom.xmlの内容は以下の通り。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>test.sample</groupId> <artifactId>test.sqlserver-analysis</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 文字コードとJavaのバージョンの設定 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <!-- プラグインの設定 --> <build> <plugins> <!-- Javaファイルのコンパイラの設定 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <!-- プロジェクトと依存するライブラリを1つにまとめる設定 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <!-- メインプログラムとして実行するクラスの指定 --> <mainClass>test.TestSqlserverAnalysis</mainClass> </manifest> </archive> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <!-- ライブラリ依存関係の設定 --> <dependencies> <dependency> <!-- SQL ServerへのJDBCドライバを追加する設定 --> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>7.0.0.jre8</version> </dependency> </dependencies> </project>
また、sqlserver_analysis.propertiesの内容は以下の通り。
copyFromGcsCmd=C:\\work\\copy_from_gcs.cmd serverName=localhost dbName=model tblName=dbo.sales tsvFilePath=c:\\work\\sqlserver\\ deleteSSASFile=c:\\work\\delete_SSASProject1.xmla deploySSASExe=c:\\Program Files (x86)\\Microsoft SQL Server\\140\\Tools\\Binn\\ManagementStudio\\Microsoft.AnalysisServices.Deployment.exe deploySSASAsdb=c:\\Users\\sql_server\\source\\repos\\SSASProject1Solution\\SSASProject1\\bin\\SSASProject1.asdatabase
さらに、TestSqlserverAnalysis.javaの内容は以下の通り。
package test; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Date; import java.util.Properties; public class TestSqlserverAnalysis { private static String copyFromGcsCmd = null; private static String serverName = null; private static String dbName = null; private static String tblName = null; private static String tsvFilePath = null; private static String deleteSSASFile = null; private static String deploySSASExe = null; private static String deploySSASAsdb = null; /** * メインクラス * * @param args 引数 */ public static void main(String[] args) { System.out.println( "*** TestSqlServerAnalysis Started. started time : " + new Date() + " ***"); long startTime = System.currentTimeMillis(); try { // プロパティファイルの値を読み込む initValuables(); // GCSのファイルをコピーする doOsCommand(new ProcessBuilder(copyFromGcsCmd) , "Get File From GCS"); // コピーしたGCSのファイルをSQLServerへのロードする loadToSqlServer(); // SqlServerAnalysisServicesにデプロイ済のSSASプロジェクトを削除する doOsCommand(new ProcessBuilder("powershell", "-Command" , "Invoke-ASCmd", "-InputFile:" + deleteSSASFile , "-Server:" + serverName), "Delete SSAS Project"); // SqlServerAnalysisServicesにSSASプロジェクトをデプロイする doOsCommand(new ProcessBuilder(deploySSASExe, deploySSASAsdb , "/s"), "Deploy SSAS Project"); } catch (Exception e) { System.out.println(e); } finally { long endTime = System.currentTimeMillis(); System.out.println( "*** TestSqlServerAnalysis Ended. ended time : " + new Date() + " ***"); System.out.println( "*** execute time : " + (endTime - startTime) / 1000.0 + "[s] ***"); } } /** * プロパティファイルの値を読み込む * * @throws IOException 入出力例外 */ private static void initValuables() throws IOException { System.out.println("--- Init Valuables Started. ---"); // プロパティファイルの値を読み込む Properties properties = new Properties(); InputStream stream = TestSqlserverAnalysis.class.getClassLoader() .getResourceAsStream("sqlserver_analysis.properties"); properties.load(stream); // プロパティファイルの値を設定する copyFromGcsCmd = properties.getProperty("copyFromGcsCmd"); serverName = properties.getProperty("serverName"); dbName = properties.getProperty("dbName"); tblName = properties.getProperty("tblName"); tsvFilePath = properties.getProperty("tsvFilePath"); deleteSSASFile = properties.getProperty("deleteSSASFile"); deploySSASExe = properties.getProperty("deploySSASExe"); deploySSASAsdb = properties.getProperty("deploySSASAsdb"); System.out.println("--- Init Valuables Ended. ---"); } /** * OSコマンドを実行する * * @param pb プロセス生成オブジェクト * @throws IOException 入出力例外 * @throws InterruptedException 割り込み例外 */ private static void doOsCommand(ProcessBuilder pb, String cmdName) throws IOException, InterruptedException { System.out.println("--- " + cmdName + " Started.---"); // 標準出力と標準エラー出力を統合 pb.redirectErrorStream(true); // OSコマンドを実行する Process process = pb.start(); // OSコマンドの標準出力を出力する InputStream is = process.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); while (true) { String line = br.readLine(); if (line == null) { break; } System.out.println(line); } // OSコマンドが完了するまで待つ process.waitFor(); System.out.println("--- " + cmdName + " Ended.---"); } /** * SQLServerへのデータロード処理を実行する * * @throws ClassNotFoundException * @throws SQLException */ private static void loadToSqlServer() throws ClassNotFoundException, SQLException { System.out.println("--- Load to SqlServer Started. ---"); // SQL Serverに接続開始 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Connection con = DriverManager.getConnection( "jdbc:sqlserver://" + serverName + ";databaseName=" + dbName + ";integratedSecurity=true;"); // Windows認証で接続 // tblNameで指定したテーブルのデータを一括削除 PreparedStatement ps = con.prepareStatement("TRUNCATE TABLE " + tblName); ps.executeUpdate(); // tblNameで指定したテーブルに、TSVファイルのデータを追加 int updCnt = 0; File[] files = new File(tsvFilePath).listFiles(); for(int i = 0; i < files.length; i++) { String fileName = files[i].getName(); if(fileName.startsWith("insert_sales_") && fileName.endsWith(".tsv")) { ps = con.prepareStatement("BULK INSERT " + tblName // 読み込みファイルを指定 + " FROM '" + tsvFilePath + fileName + "' " + " WITH (FIRSTROW = 2 " // 読み込み開始行(2行目)を指定 + ", FIELDTERMINATOR = '\\t'" // 区切り文字(タブ)を指定 + ", ROWTERMINATOR = '\\n'" // 改行文字(\n)を指定 + ", CODEPAGE = '65001'" // 文字コード(UTF-8)を指定 + ", DATAFILETYPE = 'Char')"); // データ形式(文字形式)を指定 updCnt += ps.executeUpdate(); } } // 後処理 if(ps != null) { ps.close(); } if(con != null) { con.close(); } System.out.println("update count :" + updCnt); System.out.println("--- Load to SqlServer Ended. ---"); } }
なお、上記Javaのプログラムから呼ばれる「copy_from_gcs.cmd」の内容は以下の通り。
Javaプログラムから直接gsutilコマンドを呼ぼうとした際エラーになってしまったため、別のバッチファイルとして作成している。ちなみに、「gsutil -m cp」と「-m」というオプションを付与することで、コピー処理の並列実行ができる。
本プログラムの実行結果は、以下の記事を参照のこと。
GCS(Google Cloud Storage)のファイルをSQLServerに取り込んでデータ分析を行った(1)GCS(Google Cloud Storage)に配置したファイルを、SQL Server搭載済の仮想マシンに転送し、SQL Serv...