【Java】ビルドを自動で行う

build.xmlをantでビルドする作業を自動で行います。

  • 起動バッチ

    @echo off
    set ANT_HOME=D:/Product/apache-ant-1.10.1
    set BUILD_FILE=build.xml
    set TARGET=destcopy
    set PROJECT_HOME=D:/Product/APP/
    cd %PROJECT_HOME%
    if %ERRORLEVEL%==0 (
      echo ビルドを開始します。
      echo ログは%PROJECT_HOME%/build.logに出力しています。
      call %ANT_HOME%/bin/ant -f %BUILD_FILE% -l build.log %TARGET%
    )
    if %ERRORLEVEL%==0 (
      echo ビルドを終了します。
    ) else (
      echo エラーが発生しています。ログを確認してください。
    )
    pause
    
  • build.xml

    <?xml version"1.0" encoding="UTF-8"?>
    <project name="APP-TEST" basedir="." default="destcopy">
    
      <!-- classpath指定 -->
      <path id="classpath">
        <fileset dir="./lib">
          <include name="*.jar" />
        </fileset>
        <fileset dir="./WebContent/WEB-INF/lib">
          <include name="*.jar" />
        </fileset>
    
      <!-- 初期化 -->
      <target name="clean" description="コンパイル済のclassファイルとjarファイルを削除">
        <delete dir="./dest" />
        <delete dir="./bin" />
      </target>
    
      <!-- プロジェクトコンパイル -->
      <target name="compile" depends="clean" description="コンパイル開始">
        <mkdir dir="./bin" />
        <javac debug="on" fork="true" destdir="./bin" srcdir="./src" classpathref="classpath" deprecation="on" encoding="UTF-8" includeantruntime="flase">
          <compilerarg value="-Xlint:unchecked" />
        </javac>
      </target>
    
      <!-- jarファイル作成 -->
      <target name="destcopy" depends="compile" description="jarファイル作成開始">
        <mkdir dir="./dest" />
        <copy toDir="./dest/standalone/deployments/APP-TEST.war">
          <fileset dir="./WebContent" />
        </copy>
        <copy toDir="./dest/standalone/configuration">
          <fileset dir="./jbossconfiguration" />
        </copy>
        <copy toDir="./dest/standalone/deployments/APP-TEST.war/WEB-INF/classes">
          <fileset dir="./bin/" />
        </copy>
        <touch file="./dest/standalone/deployments/APP-TEST.war.dodeploy" />
      </target>
    </project>
    

【bat】バッチファイルで全てのCSVファイル内の特定文字列を編集する

バッチファイルで同階層にあるCSVファイル内のの特定文字列を編集します。

前提条件
編集前のCSVファイル:TEST_yyyyMMddhhmmss.csv
編集後のCSVファイル:after_TEST_yyyyMMddhhmmss.csv
特定文字列:電話番号と仮定し、3桁、4桁、4桁のハイフン区切りに編集
補足:フォーマットは以下の例の通り
      電話番号は空欄の可能性あり
      電話番号の後続列は空欄の可能性あり
例
編集前
1,山田太郎,202-0003,09011112222,男
2,山田次郎,202-0003,,男
3,山田太郎,202-0003,,

編集後
1,山田太郎,202-0003,090-1111-2222,男
2,山田次郎,202-0003,,男
3,山田太郎,202-0003,,
@echo off
setlocal ENABLEDELAYEDEXPANSION
cd %~dp0
set LOG_FILE=%~n0.log
echo [ INFO ] %date% %time% CSVファイルの編集を開始します。 >>%LOG_FILE%

for %%x in (TEST_*.csv) do (
  echo %%x
  set OUTPUT_FILE=after_%%x
  type nul > !OUTPUT_FILE!

  for /f "tokens=1-5 delims=," %%a in (%%x) do (
    set STRTMP=%%d
    if not "!STRTMP!" == "" (
      if "!STRTMP:~0, 3!" == "090" (
        set STRTMP=!STRTMP:~0, 3!-!STRTMP:~4, 4!-!STRTMP:~7, 4!
        echo %%a,%%b,%%c,!STRTMP!,%%e >>!OUTPUT_FILE!
      ) else (
        echo %%a,%%b,%%c,,%%d >>!OUTPUT_FILE!
      )
    ) else (
      echo %%a,%%b,%%c,%%d,%%e >>!OUTPUT_FILE!
    )
  )
)
echo [ INFO ] %date% %time% CSVファイルの編集を終了します。 >>%LOG_FILE%
endlocal
exit /b
ポイント
・delimsでカンマ区切りを指定する。
・tokensで区切った配列のどのインデックスを利用するか決定する。
  配列は%%a~%%eで参照可能。
・値が空欄の場合、配列が詰められる。(ココがややこしい)
  1列目:配列の長さは5
  2列目:配列の長さは4
  3列目:配列の長さは3
・「type nul > !OUTPUT_FILE!」を行うことで、1度初期化してから実行している。
・繰り返し処理中は「setlocal ENABLEDELAYEDEXPANSION」~「endlocal」内で
  変数は「!XXX!」で参照可能。

【Oracle】バッチファイルからSQLPlusを起動しデータ取得

バッチファイルからSQLPlusを起動しデータ取得を行います。
主にエビデンス取得で利用します。
テスト対象の実施前後で取得し、結果ファイルを比較します。

  • 起動バッチ

    @echo off
    set DATE_TIME=%date:~0, 4%%date:~5, 2%%date:~2, 2%%time:~0, 2%%time:~3, 2%%time:~6, 2%
    
    set IP_ADDRESS=192.168.XX.XX
    set PORT_NO=1521
    set SID=XXX
    set USER_ID=XXX
    set PASSWORD=XXX
    set SQL_FILE=outputCsvAllData.sql
    set SPOOL_FILE=select_AllData.csv
    
    rem -s サイレントモード
    rem    プロンプトやログインメッセージを表示しなくなる。
    rem -L 1度だけログイン
    rem    ログインに失敗すると3回まで再試行するが、1回で終了する。
    sqlplus -s -L %USER_ID%/%PASSWORD%@%IP_ADDRESS%:%PORT_NO%/%SID% @%SQL_FILE%
    
    move %SPOOL_FILE% %DATE_TIME%_%SPOOL_FILE%
    
    echo %DATE_TIME%_%SPOOL_FILE%を出力しました。
    pause
    
  • SQLファイル(outputCsvAllData.sql)

    set echo off
    set linesize 9999
    set pagesize 0
    set trimspool on
    set feedback off
    
    spool select_AllData.csv
    @@select_AllData.sql
    spool off
    
  • 「@@」はパス名を含まないファイル名の場合、「呼び出し元のスクリプトのパス」を補完する。

    例)
    以下のフォルダ構成の場合、
    「@@」をつけると呼び出せるが、「@」の場合、エラーとなる。
    ・C:/起動バッチ
    ・C:/test/outputCsvAllData.sql
    ・C:/test/select_AllData.sql
    
  • SQLファイル(select_AllData.sql)

    prompt テーブル名
    SELECT 項目1 || 't' || 項目2 || 't' || 項目3 FROM テーブル名;
    
  • 文字列結合している理由は「【Oracle】SQLPlusで空白除去」を参照。

【bat】ディレクトリ一覧とファイル一覧を取得する

コマンドプロンプトでディレクトリ一覧とファイル一覧を取得します。
パスとファイル名のみ取得できるようにオプションを追加して取得します。

  • ディレクトリ一覧取得

    /b:不要な情報を非表示(サイズや更新時間)
    /s:ディレクトリ内を再帰表示
    /ad:表示属性はディレクトリのみ(/aが属性、/dがディレクトリ)
    
    dir /b /s /ad
    
  • ファイル一覧取得

    /a-d:表示属性はファイルのみ(-をつけることでディレクトリを除く)
    
    dir /b /s /a-d
    
  • ディレクトリ一覧とファイル一覧取得

    dir /b /s
    

【Oracle】データファイルとコントロールファイルを利用したインポート

データファイルとコントロールファイルを利用して
Oracleにデータをインポートします。

  • バッチファイル
  • @echo off
    REM == バッチファイル起動ディレクトリ取得 ==
    SET BAT_PASS=%~dp0
    
    REM == データファイルパス設定 ==
    SET DATA_PASS=%BAT_PASS%\data\
    
    REM == コントロールファイルパス設定 ==
    SET CTL_PASS=%BAT_PASS%\ctl\
    
    REM == データファイル名 ==
    SET CSVEXT=.csv
    SET CTLEXT=.ctl
    SET LOGEXT=.log
    SET DATA_ANKEN_KANRI=t_anken_kanri
    
    echo ==============================
    echo 案件管理 データファイル取込
    echo ==============================
    sqlldr USERID='TESTUSR/PASSWORD@サービス名' CONTROL='%CTL_PASS%%DATA_ANKEN_KANRI%%CTLEXT%' DATA='%DATA_PASS%%DATA_ANKEN_KANRI%%CSVEXT%' LOG='%DATA_PASS%%DATA_ANKEN_KANRI%%LOGEXT%'
    
    pause
    
  • コントロールファイル
  • OPTIONS (ERRORS=0, ROWS=10000, DIRECT=TRUE)
    LOAD DATA
    INFILE './t_anken_kanri*.csv' "str '\r\n'"
    APPEND
    INTO TABLE "TESTUSR"."T_ANKEN_KANRI"
    FILEDS TERMINATED BY ','
    OPTIONALLY ENCLOSED BY '"' AND '"'
    DATE FORMAT "YYYY/MM/DD hh24:mi:ss"
    TRAILING NULLCOLS
    (
        項目名1
        項目名2
        項目名3
    )
    
  • データファイル
  • "aaaa","bbbb","cccc"
    

【Java】指定日付の月末月初を求める

Java8のLocalDateクラスを利用して指定日付の月末月初を求めます。

// フォーマット
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
// 月初
LocalDate ldFirst = LocalDate.parse("20181015", dtf).withDayOfMonth(1);
// 月末
LocalDate ldLast = LocalDate.parse("20181015", dtf).withDayOfMonth(1).plusMonth(1).minusDays(1);

// 文字列変換
String strFirst = dtf.format(ldFirst);
String strLast = dtf.format(ldLast);

【MySQL】トランザクション管理

MySQLのトランザクションについてのメモ。
後でまとめる。

◆REPEATABLE READ
ファントムリード
スナップショットを保持している場合、発生しない。
スナップショットを保持していない場合、発生する。

ファジーリード
スナップショットを保持している場合、発生しない。
スナップショットを保持していない場合、発生する。

◆READ COMMITTED
ファントムリード
発生する。
ファジーリード
発生する。
スナップショットを保持しない。

MySQLは「REPEATABLE READ」の場合、
「START TRANSACTION;」時点でトランザクションが開始されるわけではなく、
最初のSELECTでトランザクションが開始される。
利点でもあり、欠点でもある。

ファントムリードは追加レコードを参照してしまうこと。
ファジーリードは更新レコードの値を参照してしまうこと。

【Oracle】統計情報に関するSQL

統計情報に関するSQLのメモです。

  • テーブルの統計情報を取得

    EXEC DBMS_STATS.GATHER_TABLE_STATS('スキーマ名', 'テーブル名');
    
  • インデックスの統計情報を取得

    EXEC DBMS_STATS.GATHER_INDEX_STATS('スキーマ名', 'インデックス名');
    
  • テーブルの統計情報の状態確認

    SELECT UT.TABLE_NAME, UT.NUM_ROWS, UT.BLOCKS, UT.AVG_ROW_LEN, UT.SAMPLE_SIZE, UT.LAST_ANALYZED FROM USER_TABLES UT WHERE UT.TABLE_NAME NOT IN ('CHAINED_ROWS', 'CREATE$JAVA$LOB$TABLE', 'EXCEPTIONS', 'PLAN_TABLE', 'PROF$PLAN_TABLE') AND UT.TABLE_NAME NOT LIKE 'BIN$%' ORDER BY UT.TABLE_NAME; 
    
  • インデックスの統計情報の状態確認

    SELECT UI.TABLE_NAME, UI.INDEX_NAME, UI.NUM_ROWS, UI.SAMPLE_SIZE, UI.LAST_ANALYZED, UI.STATUS FROM USER_INDEXES UI WHERE UI.TABLE_NAME NOT IN ('CHAINED_ROWS', 'CREATE$JAVA$LOB$TABLE', 'EXCEPTIONS', 'PLAN_TABLE', 'PROF$PLAN_TABLE') AND UI.TABLE_NAME NOT LIKE 'BIN$%' ORDER BY UI.TABLE_NAME, UI.INDEX_NAME;
    

【Oracle】パスワードの有効期限

VMwareにOracle11gをインストールしているのですが、
久しぶりにsqlplusにログインしたところ以下のエラーが発生しました。

ERROR:
ORA-28002: the password will expire within 7 days

Oracle10gまではパスワードは無期限でしたが、
Oracle11gからはパスワードの有効期限があるようです。
パスワードの期限を無期限に変更し、
パスワードを再設定します。

sqlplusに管理者権限を持つユーザかsysユーザでログインします。

sqlplus sys/管理者パスワード as sysdba

以下のSQLを実行します。

alter profile default limit password_life_time unlimited;
alter user ユーザ名 identified by "パスワード";

パスワードはダブルクォーテーションで括らないとエラーになります。
記号の区別がつかないためと思われます。

【SQLServer】データのエクスポートとインポート

データのエクスポートとインポートをBCPユーティリティを利用して行います。

bcp データベース名.所有者(初期はdbo).テーブル名 in|out|queryout|format ファイル名 オプション
bcp Test_db.dbo.TestTbl out TestTbl.txt /U ユーザ名 /S サーバ名 /P パスワード /c /t , /r \r\n /q >> exec.log
/c /cを指定しない場合、列ごとにプロンプトでタブや改行を指定する必要がある。
/t /cを指定した場合、デフォルトはタブ区切りになる。変更する場合に指定。
/r /cを指定した場合、デフォルトは\nになる。変更する場合に指定。
/q 空白や単一引用符を含むデータベース名、所有者、テーブル名を指定する場合に指定。
/o bcpコマンド単位でログ出力できる。「>> ファイル名」の方が楽。
/f フォーマット個別指定。/cの方が楽。
   以下がフォーマット。
   8.0
   2
   1 SQLCHAR     0 3 "," 1 USERID Japanese_BIN
   2 SQLDATETIME 0 8 "," 2 DATE   ""

   1行目:バージョン番号
   2行目:列数
   3行目:番号、データ型、プレフィックス長、項目長、終端文字、DB内の項目番号、DB内の項目名、行の照合順序(※1)

※1
照合順序の例
 Japanese_BIN
  大文字、小文字、シングルバイト、ダブルバイト、ひらがな、カタカナを全て区別する
 Japanese_CI_AS
  大文字、小文字、シングルバイト、ダブルバイト、ひらがな、カタカナを全て区別しない

複数テーブルに対して作成する場合、
以下のようなSQL文を準備しておくと汎用性が高くなる。

SELECT 'bcp Test_db.dbo.' + name + ' out ' + name + '.txt /U ユーザ名 /S サーバ名 /P パスワード /c /t "," /r \r\n' FROM sysobjects WHERE type = 'U' ORDER BY name;