001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.plugin.query; 017 018import java.sql.Connection; 019import java.sql.CallableStatement; 020import java.sql.ResultSet; 021import java.sql.SQLException; 022import java.sql.Types; 023import java.sql.Array; // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ) 対応。oracle.sql.ARRAY の置き換え 024import java.util.Map; 025 026import oracle.jdbc.OracleConnection; // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ) 対応 027import oracle.jdbc.OracleTypes; // CURSOR が残る 028import oracle.jdbc.OracleCallableStatement; // CURSOR が残る 029 030import org.opengion.hayabusa.db.AbstractQuery; 031import org.opengion.hayabusa.db.DBErrMsg; 032import org.opengion.hayabusa.common.HybsSystemException; 033import org.opengion.fukurou.util.ErrorMessage; 034import org.opengion.fukurou.util.StringUtil; 035 036/** 037 * エントリ系 PL/SQL をコールして、結果カーソルから、DBTableModel を作成します。 038 * 039 * java.sql.CallableStatement を用いて、データベース検索処理を行います。 040 * 引数を配列指定で渡すことが出来、エラー時には、DBErrMsg オブジェクトにエラー情報を 041 * 格納して返すことが可能です。 042 * 内部変数の受け渡しのデフォルト実装は、AbstractQuery クラスを継承している 043 * ため、ここでは、execute() メソッドを実装しています。 044 * このクラスでは、ステートメント文を execute() する事により、データベースを 045 * 検索した結果を DBTableModel に割り当てます。 046 * 047 * @og.formSample 048 * 例:jsp/TYPESB/result.jsp (検索系:カーソル返し) 049 * 例:jsp/TYPE3B/entry.jsp (エントリ系) 050 * names には、ARG_ARRAY 配列に順次セットされます。 051 * 使用する場合は、一旦わかり易い変数に受けて利用してください。 052 * 呼び出す PL/SQL では、検索系PL/SQL です。(下記の例は、エントリ系) 053 * 054 * <og:query 055 * command = "NEW" 056 * names = "SYSTEM_ID,LANG,CLM,NAME_JA,LABEL_NAME,KBSAKU,USER.ID" 057 * queryType = "JDBCErrMsg" 058 * displayMsg = "" > 059 * {call TYPE3B01.TYPE3B01(?,?,?,?)} 060 * </og:query> 061 * 062 * CREATE OR REPLACE PACKAGE TYPE3B01 AS 063 * TYPE CUST_CURSOR IS REF CURSOR; 064 * PROCEDURE TYPE3B01( 065 * P_KEKKA OUT NUMBER, 066 * P_ERRMSGS OUT ERR_MSG_ARRAY, 067 * P_RC1 OUT CUST_CURSOR, 068 * P_ARGS IN ARG_ARRAY ); 069 * END; 070 * 071 * P_SYSTEM_ID GEA08.SYSTEM_ID%TYPE := P_ARGS(1); --システムID 072 * P_LANG GEA08.LANG%TYPE := P_ARGS(2); --言語 073 * P_CLM GEA08.CLM%TYPE := P_ARGS(3); --項目 074 * P_NAME_JA GEA08.NAME_JA%TYPE := P_ARGS(4); --名称(漢字) 075 * P_LABEL_NAME GEA08.LABEL_NAME%TYPE := P_ARGS(5); --表示名称 076 * P_KBSAKU GEA08.KBSAKU%TYPE := P_ARGS(6); --作成区分 077 * P_USRSET GEA08.USRSET%TYPE := P_ARGS(7); --登録者 078 * 079 * @og.group データ表示 080 * @og.group データ編集 081 * 082 * @version 4.0 083 * @author Kazuhiko Hasegawa 084 * @since JDK5.0, 085 */ 086public class Query_JDBCErrMsg extends AbstractQuery { 087 /** このプログラムのVERSION文字列を設定します。 {@value} */ 088 private static final String VERSION = "8.5.4.2 (2024/01/12)" ; 089 090 /** 091 * デフォルトコンストラクター 092 * 093 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 094 */ 095 public Query_JDBCErrMsg() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 096 097 /** 098 * 引数配列付のクエリーを実行します。 099 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 100 * これは、CallableStatement を用いて、データベース検索処理を行います。 101 * {call TYPE3B01.TYPE3B01(?,?,?,?)} で、4番目の引数には、 102 * names で指定したリクエスト情報が、ARG_ARRAY 配列に順次セットされます。 103 * 使用する場合は、一旦わかり易い変数に受けて利用してください。 104 * 呼び出す PL/SQL では、検索系PL/SQL です。 105 * 106 * @og.rev 2.3.1.3 (2003/01/28) Open Cursor が、大量に残る件の対応。ResultSet を close() 107 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 108 * @og.rev 3.3.3.1 (2003/07/18) DB登録時の後ろスペースを削除する。 109 * @og.rev 3.5.2.0 (2003/10/20) 内部オブジェクトタイプ名を システムパラメータ で定義します。 110 * @og.rev 3.5.6.0 (2004/06/18) nullに対する無駄な比較を削除します。 111 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。 112 * @og.rev 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 113 * @og.rev 6.3.6.1 (2015/08/28) close(),realClose() 廃止。Queryはキャッシュしません。 114 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 115 * @og.rev 6.9.3.0 (2018/03/26) DB_FETCH_SIZE追加。 116 * @og.rev 7.0.5.0 (2019/09/24) カーソルが null の場合チェックとエラーメッセージを追加。 117 * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 ExceptionAsFlowControl 対応 118 * 119 * @param args オブジェクトの引数配列(可変長引数) 120 */ 121 @Override 122 public void execute( final String... args ) { // 6.1.1.0 (2015/01/17) refactoring 123 try { 124 final Connection conn = getConnection(); // close() 処理は、呼び出しもとで行う。 125 // 6.4.2.1 (2016/02/05) try-with-resources 文 126 try( CallableStatement callStmt = conn.prepareCall( getStatement() ) ) { 127 callStmt.setQueryTimeout( DB_MAX_QUERY_TIMEOUT ); 128 callStmt.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) 129 130 final Map<String,Class<?>> map = conn.getTypeMap(); 131 map.put( ERR_MSG,DBErrMsg.class ); // 4.0.0 (2005/01/31) 132 133 // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 http://docs.oracle.com/cd/E28389_01/web.1111/b60995/thirdparty.htm 134 final Array newArray = ((OracleConnection)conn).createOracleArray( ARG_ARRAY, StringUtil.rTrims( args )); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 135 136 callStmt.registerOutParameter(1, Types.INTEGER); 137 callStmt.registerOutParameter(2, Types.ARRAY,ERR_MSG_ARRAY); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 138 callStmt.registerOutParameter(3, OracleTypes.CURSOR); 139 callStmt.setArray( 4,newArray ); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 140 141 callStmt.execute(); 142 143 final int rtnCode = callStmt.getInt(1); 144 setErrorCode( rtnCode ); 145 if( rtnCode < ErrorMessage.NG ) { // 異常以外(警告か正常)の場合 146 try( ResultSet resultSet = ((OracleCallableStatement)callStmt).getCursor(3) ) { 147 // 7.0.5.0 (2019/09/24) カーソルが null の場合チェックとエラーメッセージを追加。 148 if( resultSet == null ) { 149 setErrorCode( ErrorMessage.EXCEPTION ); 150 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ExceptionAsFlowControl 対応 151// final String errMsg = "Query_JDBCErrMsg Return CURSOR Not Found !!" + CR; 152// throw new HybsSystemException( errMsg ); 153 final ErrorMessage errMessage = new ErrorMessage( "Query_JDBCErrMsg Return CURSOR Not Found !!" ); 154 setErrorMessage( errMessage ); 155 return; 156 } 157 else { 158 createTableModel( resultSet ); 159 } 160 } 161 } 162 if( rtnCode > ErrorMessage.OK ) { // 正常以外(警告、異常、それ以上)の場合 163 final ErrorMessage errMessage = new ErrorMessage( "Query_JDBCErrMsg Error!!" ); 164 final Array rtn3 = callStmt.getArray(2); // 6.0.0.0 (2014/04/11) Oracle11g(11.2.0.3のドライバ)対応 165 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach 166// final Object[] rtnval3 = (Object[])rtn3.getArray(); 167// for( int i=0; i<rtnval3.length; i++ ) { 168// final DBErrMsg er = (DBErrMsg)rtnval3[i]; 169 for( final Object rtnval : (Object[])rtn3.getArray() ) { 170 final DBErrMsg er = (DBErrMsg)rtnval; 171 if( er == null ) { break; } 172 errMessage.addMessage( er.getErrMsg() ); 173 } 174 setErrorMessage( errMessage ); 175 } 176 } 177 } 178 catch( final SQLException ex) { 179 setErrorCode( ErrorMessage.EXCEPTION ); 180 final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR 181 + getStatement() + CR; 182 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 183 } 184 } 185}