!!!DBAccessor JDBC経由でDBを操作するクラス {{code Java, import java.sql.*; import java.util.ArrayList; import java.util.HashMap; /** * DBにアクセスするためのクラス */ public class DBAccessor implements Cloneable { /** エラーをどこにも出力しない */ final public static int TO_NO = 0; /** エラーをコンソールに出力する */ final public static int TO_CONSOLE = 1; /** エラーをLogを使って出力する */ final public static int TO_LOG = 2; /** エラーをDialogに出力する */ final public static int TO_DIALOG = 3; /** データを読み込むモード */ public static enum MODE { ALL, //全データを読み込む ONE //1レコードだけ読み込む } /** エラー時にログの出力先 */ protected int errorLog = TO_CONSOLE; /** データベースコネクション */ protected Connection con = null; /** 接続文字列(URL) */ protected String connectionString = null; /** ドライバ名 */ protected String driverName = null; /** パスワード */ protected String pass = null; private static DBAccessor self = null; /** ユーザ名 */ protected String user = null; /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード */ public DBAccessor(String driverName, String connectionString, String user, String pass) { this(driverName, connectionString, user, pass, TO_CONSOLE); } /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか */ public DBAccessor(String driverName, String connectionString, String user, String pass, int errorLog) { this.errorLog = errorLog; this.driverName = driverName; this.connectionString = connectionString; this.user = user; this.pass = pass; try { Class.forName(driverName); } catch (Exception e) { this.outputException(e); } } @Override public Object clone(){ return new DBAccessor( this.driverName, this.connectionString, this.user, this.pass, this.errorLog); } /** 接続を閉じる */ public void close() { if (!isClosed()) { try { con.close(); } catch (Exception e) { this.outputException(e); } con = null; } } /** * データベースに接続し、SQL 文をデータベースに送るための Statement オブジェクトを生成します。 * *@return 新しいデフォルト Statement オブジェクト *@exception SQLException データベースアクセスエラーが発生した場合、このメソッドがクローズされた接続に対して呼び出された場合、または指定されたパラメータが型および並行処理を示す ResultSet 定数でない場合 */ public Statement createStatement() throws SQLException{ if (connect()){ return con.createStatement(); } return null; } /** * データベースに接続し、パラメータ付き SQL 文をデータベースに送るための PreparedStatement オブジェクトを生成します。 * *@param sql 1 つ以上の '?' IN パラメータプレースホルダーを含めることができる SQL 文 *@return プリコンパイルされた SQL 文を含む新しいデフォルトの PreparedStatement オブジェクト *@exception SQLException データベースアクセスエラーが発生した場合、またはこのメソッドがクローズされた接続について呼び出された場合 */ public PreparedStatement prepareStatement(String sql) throws SQLException { if (connect()){ return con.prepareStatement(sql); } return null; } /** * データベースのストアドプロシージャーを呼び出すための CallableStatement オブジェクトを生成します * *@param sql - 1 つ以上の '?' パラメータプレースホルダーを含めることができる SQL 文。 通常この文は、JBDC 呼び出しのエスケープ構文を使用して指定される *@return プリコンパイルされた SQL 文を含む新しいデフォルトの CallableStatement オブジェクト *@exception SQLException データベースアクセスエラーが発生した場合、またはこのメソッドがクローズされた接続について呼び出された場合 */ public CallableStatement prepareCall(String sql) throws SQLException { if (connect()){ return con.prepareCall(sql); } return null; } /** * 指定された Statmentクラス インスタンスを解放します。 * *@param st Statmentクラス インスタンス */ public void close(Statement st){ if (st != null){ try { st.close(); } catch (Exception e){ this.outputException(e); } } } /** * 指定された ResultSetクラス インスタンスを解放します。 * *@param rs ResultSetクラス インスタンス */ public void close(ResultSet rs){ if (rs != null){ try { rs.close(); } catch (Exception e){ this.outputException(e); } } } /** * 指定された Statmentクラス インスタンス と ResultSetクラス インスタンス を解放します。 * *@param st Statmentクラス インスタンス *@param rs ResultSetクラス インスタンス */ public void close(Statement st, ResultSet rs){ close(rs); close(st); } /** * コミット処理をする * *@return コミット処理に成功した場合はTrue、それ以外はFalse。 */ public boolean commit() { if (isClosed()) { return false; } try { con.commit(); return true; } catch (Exception e) { this.outputException(e); return false; } } /** * データベース接続 * *@return 接続に成功した場合はTrue、それ以外はFalse。 */ public boolean connect() throws SQLException{ boolean result = false; if (isClosed()) { con = DriverManager.getConnection(connectionString, user, pass); con.setAutoCommit(false); result = true; } else { // Log.getLogger().severe("既に接続されています"); result = true; } return result; } /** * 指定されたパラメータからDBAccessorインスタンスを返す。 * getInstance() を使用することにより、生成された * インスタンスを取り出すことが出来る。

* もし、以前に生成されたインスタンスがあれば接続を閉じる。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@return 生成したDBAccessorのインスタンス */ public static DBAccessor createInstance(String driverName, String connectionString, String user, String pass) { return createInstance(driverName, connectionString, user, pass, TO_CONSOLE); } /** * 指定されたパラメータからDBAccessorインスタンスを返す。 * getInstance() を使用することにより、生成された * インスタンスを取り出すことが出来る。

* もし、以前に生成されたインスタンスがあれば接続を閉じる。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか *@return 生成したDBAccessorのインスタンス */ public static DBAccessor createInstance(String driverName, String connectionString, String user, String pass, int errorLog) { if (self != null && !self.isClosed()){ self.close(); } self = new DBAccessor(driverName, connectionString, user, pass, errorLog); return getInstance(); } /** * createInstance()メソッドによって生成されたインスタンスを * 取得する。 * *@return createInstanceによって生成されたDBAccessorインスタンス */ public static DBAccessor getInstance() { return self; } /** * createInstance()メソッドによって生成されたインスタンスから * 新しいDBAccessorを返す * *@return createInstanceによって生成されたDBAccessorインスタンスから * 生成された新しいDBAccessor */ public static DBAccessor newInstance() { return (DBAccessor)getInstance().clone(); } /** * 接続状態を返す。 * *@return 閉じている場合はTrue。 */ public boolean isClosed() { try { return (con == null || con.isClosed()); } catch (Exception e) { this.outputException(e); return true; } } /** * ロールバック処理をする * *@return Description of the Return Value */ public boolean rollback() { if (isClosed()) { return false; } try { con.rollback(); return true; } catch (Exception e) { this.outputException(e); return false; } } /** * 指定された Exceptionクラス インスタンスよりエラーを出力します。 * *@param e Exceptionクラス インスタンス */ private void outputException(Exception e){ switch (errorLog) { case TO_LOG: //Log.logStackTrace(e); break; case TO_CONSOLE: System.out.println(e); break; case TO_NO: break; case TO_DIALOG: javax.swing.JOptionPane.showMessageDialog(null, e); break; } } /** * 指定されたエラーの出力先をセットします。 * *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか */ public void setErrorLog(int errorLog){ this.errorLog = errorLog; } /** * データベースのコネクションを返します。 * *@return データベースコネクション */ public Connection getConnection() throws SQLException{ if (connect()){ return con; } return null; } /** * パラメータの型に合わせて PreparedStatement にパラメータをセットする。 * *@param st PreparedStatementインスタンス *@param param パラメータのArrayList *@exception Exception 処理中に発生した例外 */ public void setParameters(PreparedStatement st, ArrayList param) throws Exception { setParameters(st, param.toArray()); } /** * パラメータの型に合わせて PreparedStatement にパラメータをセットする。 * *@param st PreparedStatementインスタンス *@param param パラメータのObject配列 *@exception Exception 処理中に発生した例外 */ public void setParameters(PreparedStatement st, Object[] param) throws Exception { for (int i = 0; i < param.length; i++) { if (param[i] instanceof Long){ st.setLong(i + 1, (Long)param[i]); } else if (param[i] instanceof Double){ st.setDouble(i + 1, (Double)param[i]); } else if (param[i] instanceof Integer){ st.setInt(i + 1, (Integer)param[i]); } else if (param[i] instanceof java.sql.Date){ st.setDate(i + 1, (java.sql.Date)param[i]); } else { st.setString(i + 1, (String)param[i]); } } } /** * 指定されたSQLを実行し、実行結果を ArrayList で返す。 * * @param sql 実行する SQL文 * @param mode 戻り値のモード。ALL の場合は全件、ONE の場合は最初の1件を返す。 */ public ArrayList executeQuery(String sql, MODE mode) throws Exception { if (!connect()){ return null; } PreparedStatement st = con.prepareStatement(sql); ArrayList args = new ArrayList(); return executeQuery(st,args, mode); } /** * 指定された PreparedStatement を実行し、実行結果を ArrayList で返す。 * * @param st 実行する PreparedStatement * @param args PreparedStatement の引数。必要ない場合は null。 * @param mode 戻り値のモード。ALL の場合は全件、ONE の場合は最初の1件を返す。 */ public ArrayList executeQuery(PreparedStatement st, ArrayList args, MODE mode) throws Exception { ResultSet rs = null; ArrayList rows = null; try { if (args == null){ args = new ArrayList(); } ResultSetMetaData rsmd = null; setParameters(st,args); rs = st.executeQuery(); rsmd = rs.getMetaData(); int colCnt = rsmd.getColumnCount(); String colLabel = ""; rows = new ArrayList(); while(rs.next()){ HashMap row = new HashMap(); for (int i = 0; i < colCnt; i++){ colLabel = rsmd.getColumnLabel(i+1); row.put(colLabel,rs.getObject(colLabel)); } rows.add(row); if (mode == MODE.ONE){ break; } } return rows; } finally { close(st,rs); } } } }} !!!DBPoolManager DBAccessorをプールするクラス。 {{code Java, import java.util.*; public class DBPoolManager { /** 接続文字列(URL) */ private String connectionString = null; /** ドライバ名 */ private String driverName = null; /** パスワード */ private String pass = null; /** ユーザ名 */ private String user = null; /** エラー時にログの出力先 */ protected int errorLog = DBAccessor.TO_CONSOLE; /** ロックオブジェクト */ private byte[] lock = new byte[0]; /** プール */ private HashStack pool; /** 管理しているすべてのオブジェクト */ private HashSet allList; /** 自動クローズ処理用タイマー */ private Timer closeTimer; /** 最後に使用されてから自動クローズするまでの時間 */ private long closeTime; /** 最後に使用されてから自動クローズするまでの時間 のデフォルト値 */ final static private long DEFAULT_DELAY = 1000 * 60 * 60; /** 自分自身のオブジェクト */ private static DBPoolManager self = null; /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード */ public DBPoolManager(String driverName, String connectionString, String user, String pass, int poolSize) { this(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE,poolSize); } /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか *@param poolSize プールのサイズ */ public DBPoolManager(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize) { this(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE,poolSize, DEFAULT_DELAY); } /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか *@param poolSize プールのサイズ *@param closeTime 使用していないコネクションを閉じるまでの時間(ミリ秒) */ public DBPoolManager(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize, long closeTime) { this.driverName = driverName; this.connectionString = connectionString; this.user = user; this.pass = pass; this.errorLog = errorLog; this.closeTime = closeTime; if (poolSize < 1){ poolSize = 10; } pool = new HashStack(); for(int i = 0; i < poolSize; i++){ pool.push(null); } allList = new HashSet(); startTimer(closeTime / 10); } /** * プールされているコネクションを自動的に * クローズするためのタイマーを開始する * *@param delay コネクションを自動的に閉じるまでの時間 */ public void startTimer(long delay){ if (this.closeTimer != null){ stopTimer(); } this.closeTimer = new Timer(); TimerTask task = new TimerTask(){ @Override public void run(){ closeNotUsed(); } }; this.closeTimer.schedule(task, delay, delay); } /** * プールされているコネクションを自動的に * クローズするためのタイマーを止める */ public void stopTimer(){ if (this.closeTimer != null){ this.closeTimer.cancel(); this.closeTimer = null; } } /** * 管理しているコネクションをすべて閉じて、 * メモリを開放する */ public void dispose(){ closeAll(); stopTimer(); } /** * 指定されたパラメータからDBAccessorインスタンスを返す。 * getInstance() を使用することにより、生成された * インスタンスを取り出すことが出来る。

* *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param poolSize プールのサイズ */ public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int poolSize) { return createInstance(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE, poolSize); } /** * 指定されたパラメータからDBAccessorインスタンスを返す。 * getInstance() を使用することにより、生成された * インスタンスを取り出すことが出来る。

* *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか *@param poolSize プールのサイズ */ public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize) { return createInstance(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE, poolSize, DEFAULT_DELAY); } /** * 指定されたパラメータからDBAccessorインスタンスを返す。 * getInstance() を使用することにより、生成された * インスタンスを取り出すことが出来る。

* *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか *@param poolSize プールのサイズ *@param closeTime 使用していないコネクションを閉じるまでの時間(ミリ秒) */ public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize, long closeTime) { if (self != null){ self.dispose(); } self = new DBPoolManager( driverName, connectionString, user, pass, errorLog, poolSize, closeTime); return getInstance(); } /** * createInstance()メソッドによって生成されたインスタンスを * 取得する。 * *@return createInstanceによって生成された DBPoolManager インスタンス */ public static DBPoolManager getInstance() { return self; } /** * DBAccessor を返す。 * *@return DBAccessor */ public DBAccessor getDBAccessor(){ synchronized(lock){ // System.out.println("get " + Thread.currentThread()); while(pool.empty()){ try { // System.out.println("lock " + Thread.currentThread()); lock.wait(); } catch (Exception e){ } } // System.out.println("get2 " + Thread.currentThread()); DBAccessor db = pool.pop(); if (db == null){ db = new DBAccessorForPool( this, driverName, connectionString, user, pass, errorLog ); allList.add(db); } return db; } } /** * DBAccessor をプールへ戻す * *@param db プールへ戻す DBAccessor */ private void pushDBAccessor(DBAccessor db){ synchronized(lock){ // System.out.println("push " + Thread.currentThread()); if (allList.contains(db) && !pool.contains(db)){ pool.push(db); // System.out.println("notify " + Thread.currentThread()); lock.notify(); } } } /** * 管理しているコネクションをすべて閉じる * */ private void closeAll(){ for(DBAccessor db : allList){ if (db instanceof DBAccessorForPool){ ((DBAccessorForPool)db).closeConnection(); } else { db.close(); } } } /** * 使用されていないコネクションを閉じる * */ private void closeNotUsed(){ synchronized(lock){ Iterator iterator = pool.iterator(); long nowTime = System.currentTimeMillis(); while(iterator.hasNext()){ DBAccessor dba = iterator.next(); if (dba != null && !dba.isClosed() && dba instanceof DBAccessorForPool){ DBAccessorForPool dbafp = (DBAccessorForPool)dba; long lastUseTime = dbafp.getLastUseTime(); if ( nowTime - lastUseTime > closeTime ){ dbafp.closeConnection(); } } } } } static class HashStack { private HashSet set; private Stack stack; public HashStack(){ set = new HashSet(); stack = new Stack(); } public void push(T t){ set.add(t); stack.push(t); } public T pop(){ T t = stack.pop(); set.remove(t); return t; } public int size(){ return set.size(); } public Iterator iterator() { return set.iterator(); } public boolean contains(T t){ return set.contains(t); } public boolean empty(){ return stack.empty(); } } static class DBAccessorForPool extends DBAccessor { private DBPoolManager manager; private long lastUseTime; /** * コンストラクタ。 * *@param driverName DBドライバ名 *@param connectionString DB接続文字列(URL) *@param user ユーザー名 *@param pass パスワード *@param errorLog エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか */ public DBAccessorForPool(DBPoolManager manager, String driverName, String connectionString, String user, String pass, int errorLog) { super(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE); this.manager = manager; this.lastUseTime = System.currentTimeMillis(); } private void closeConnection(){ super.close(); } @Override public void close(){ rollback(); this.lastUseTime = System.currentTimeMillis(); manager.pushDBAccessor(this); } public long getLastUseTime(){ return lastUseTime; } } } }} {{category2 プログラミング言語,Java}}