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.PreparedStatement; 019import java.sql.ResultSet; 020import java.sql.SQLException; 021 022import org.opengion.hayabusa.common.HybsSystemException; 023import org.opengion.hayabusa.db.AbstractQuery; 024import org.opengion.fukurou.util.ErrorMessage; 025import org.opengion.fukurou.util.StringUtil; 026 027/** 028 * 引数引き当て(PreparedStatement) を利用した登録系Queryです。 029 * 030 * java.sql.PreparedStatement を用いて、データベース検索処理を行います。 031 * 引数に、指定した値を配列で渡します。 032 * 内部変数の受け渡しのデフォルト実装は、AbstractQuery クラスを継承している 033 * ため、ここでは、execute() メソッドを実装しています。 034 * このクラスでは、ステートメント文を execute() する事により、データベースを 035 * 検索した結果を DBTableModel に割り当てます。 036 * 037 * このクラスは、Query で使用されるより、内部の DBTableModelUtilから、 038 * 利用されるケースが主です。 039 * Query で使用する場合は、JDBCPrepared ではなく、JDBCTableUpdate を 040 * 使用することを、ご検討ください。 041 * 042 * ※postgres8.3以降では、数値型の列に対して、実行した場合は、型相違のエラーが発生します。 043 * postgres8.3以降で利用する場合は、postgres側に暗黙の型変換(CAST)の実装を検討して下さい。 044 * 045 * @og.formSample 046 * 例: 047 * 可変引数付きのSQL文を実行します。 048 * これは、INSERT,UPDATE,DELETE など、どのようなSQL文でも実行できます。 049 * names 属性で指定するのは、DBTableModelのカラム名で、その値が順番に、 050 * 引数(?記号)の個所に設定されます。 051 * 選択されたデータ(行)の数だけ、繰り返し実行されます。 052 * 053 * jsp/TYPE1A/copy.jsp 054 * <og:value scope="session" 055 * key="names" 056 * value="CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG" /> 057 * <og:value scope="session" key="SQL" > 058 * INSERT INTO GEA08 059 * (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG, 060 * FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD) 061 * VALUES 062 * (?,?,?,?,?,?, 063 * '1','{@USER.YMDH}','{@USER.YMDH}','{@USER.ID}','{@USER.ID}','{@GUI.KEY}') 064 * </og:value> 065 * 066 * jsp/TYPE1A/entry.jsp 067 * <h:tableUpdate 068 * command = "{@command}" 069 * queryType = "JDBCPrepared" 070 * names = "{@names}" > 071 * {@SQL} 072 * </og:tableUpdate> 073 * 074 * <!-- 前画面で指定のSQL文を削除します。(scope="session"なので削除が必要。) --> 075 * <og:value scope="session" key="names" command="REMOVE" /> 076 * <og:value scope="session" key="SQL" command="REMOVE" /> 077 * 078 * 以下はSELECTで使用する場合の例 079 * ※値はnamesに指定した値が、?に順番に設定されます。 080 * (andタグのplaceHolder属性は、valueに指定した式を、実行する or 実行しないの判定に利用されます。) 081 * <og:query command="NEW" queryType="JDBCPrepared" names="NO,NAME,KBN"> 082 * SELECT 083 * NO,NAME,KBN 084 * FROM 085 * T01 086 * <og:where> 087 * <og:and value="NO = ?" placeHolder="{@NO}" /> 088 * <og:and value="NAME LIKE ? || '%'" placeHolder="{@NAME}" /> 089 * <og:and value="KBN IN (?)" multi="true" placeHolder="{@KBN}"/> 090 * </og:where> 091 * </og:query> 092 * 093 * @og.group データ表示 094 * @og.group データ編集 095 * 096 * @version 4.0 097 * @author Kazuhiko Hasegawa 098 * @since JDK5.0, 099 */ 100public class Query_JDBCPrepared extends AbstractQuery { 101 /** このプログラムのVERSION文字列を設定します。 {@value} */ 102 private static final String VERSION = "6.9.3.0 (2018/03/26)" ; 103 104 /** 105 * デフォルトコンストラクター 106 * 107 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor. 108 */ 109 public Query_JDBCPrepared() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 110 111 /** 112 * 引数配列付のクエリーを実行します。 113 * 処理自体は、#execute() と同様に、各サブクラスの実装に依存します。 114 * これは、PreparedQuery で使用する引数を配列でセットするものです。 115 * select * from emp where deptno = ? and job = ? などの PreparedQuery の 116 * ? 部分の引数を 117 * 順番にセットしていきます。 118 * 119 * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更 120 * @og.rev 2.3.1.3 (2003/01/28) Open Cursor が、大量に残る件の対応。ResultSet を close() 121 * @og.rev 3.1.1.0 (2003/03/28) 同期メソッド(synchronized付き)を非同期に変更する。 122 * @og.rev 3.3.3.1 (2003/07/18) DB登録時の後ろスペースを削除する。 123 * @og.rev 3.5.6.0 (2004/06/18) PreparedStatement をexecute 間で使いまわします。 124 * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。 125 * @og.rev 5.3.8.0 (2011/08/01) pstmt.setObject で、useParamMetaData の判定を避けるため、pstmt.setString で代用(PostgreSQL対応) 126 * @og.rev 6.3.6.1 (2015/08/28) close(),realClose() 廃止。Queryはキャッシュしません。 127 * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。 128 * @og.rev 6.9.3.0 (2018/03/26) DB_FETCH_SIZE追加。 129 * 130 * @param args オブジェクトの引数配列(可変長引数) 131 */ 132 @Override 133 public void execute( final String... args ) { // 6.1.1.0 (2015/01/17) refactoring 134 135 // 6.4.2.1 (2016/02/05) try-with-resources 文 136 try( PreparedStatement pstmt = getConnection().prepareStatement( getStatement() ) ) { 137 pstmt.setQueryTimeout( DB_MAX_QUERY_TIMEOUT ); 138 139 // 6.1.1.0 (2015/01/17) refactoring. 可変引数にしたため、null は来ない。 140 for( int i=0; i<args.length; i++ ) { 141 pstmt.setString( i+1,StringUtil.rTrim( args[i] ) ); // 5.3.8.0 (2011/08/01) 処理の簡素化 142 } 143 144 if( pstmt.execute() ) { 145 try( ResultSet resultSet = pstmt.getResultSet() ) { 146 resultSet.setFetchSize( DB_FETCH_SIZE ); // 6.9.3.0 (2018/03/26) 147 createTableModel( resultSet ); 148 setUpdateFlag( false ); 149 } 150 } 151 else { 152 setExecuteCount( pstmt.getUpdateCount() ); 153 } 154 155 setErrorCode( ErrorMessage.OK ); 156 } 157 catch( final SQLException ex ) { // catch は、close() されてから呼ばれます。 158 setErrorCode( ErrorMessage.EXCEPTION ); 159 160 final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR 161 + getStatement() + CR; 162 throw new HybsSystemException( errMsg,ex ); // 3.5.5.4 (2004/04/15) 引数の並び順変更 163 } 164 } 165 166}