LaBee Framework データベース操作

LaBee FrameworkはJavaによるWebシステム開発のデファクトスタンダードを目指す、ゼロから作られた国産のJavaフレームワークです。 海外製フレームワーク特有の難解さや情報不足による工数や人員の増大を解消しJavaのWeb開発を効率化する為に作られました。 LGPLライセンスでソースコードをオープンソース公開しており、個人・企業問わずどなたでも無償で利用出来ます
https://www.bee-wkspace.com/
![press.jpg](https://qiita-image-store.s3.amazonaws.com/0/137533/9ec50bce-b5dd-3ed3-f1f3-c6f5e9a4d106.jpeg)


#データベース操作

##データベース接続 

LaBeeFrameworkはデータベースとのJDBC接続をデータソースを使用して行ないます。
事前に以下の設定を行ないます。 

- LaBeeFramework.propertiesのデータソース名項目(DATA_SOURCE_NAME)を設定する（デフォルトではjdbc/webApp)
- LaBeeFramework.propertiesのデータベース使用フラグ項目(USE_DATABASE_FLG)をtrueに設定する
- JDBCドライバクラスをWEB-INF/libに配置するか、LaBeeFramework.propertiesのJDBCドライバパス項目(JDBC_DRIVER)にJDBCドライバのフルパスディレクトリパスを設定する
- LaBeeFramework.propertiesのデータベース種別項目(DATABASE_TYPE)を設定(動作確認はMySQLのみ対応しています)
- META-INFフォルダ配下にcontext.xmlファイルを作り、以下書式のDB接続情報を設定します。(設定項目内容は自環境に合わせて設定する) 

~~~
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Context reloadable="false">
  <Resource 
    auth="Container" 
    defaultAutocommit="false"
    driverClassName="com.mysql.jdbc.Driver" 
    maxActive="20" maxIdle="30000" maxWait="100"
    type="javax.sql.DataSource"
    name="jdbc/webApp" 
    username="test_user"
    password="test_pass" 
    url="jdbc:mysql://localhost:3306/labee"/>
</Context>
~~~
- nameパラメータ値はLaBeeFramework.propertiesのデータソース名項目(DATA_SOURCE_NAME)と同じ値を設定します 

LaBeeFrameworkでデータベースとのアクセスはcom.bee_wkspace.labee_fw.common.db.DBAccessクラスを使用します。 DBAccessはDBとの接続、切断、SQL実行等の機能を持っています。DBとの接続、切断は以下のようにして呼び出します。 


~~~
      DBAccess dba = new DBAccess();
      
      // DB接続オープン
      dba.openDB();
      
      // DB接続切断
      dba.close();
~~~

ただし通常ビジネスロジックを実装する際はビジネスロジック親クラスcom.bee_wkspace.labee_fw.app.base.AppBaseBlogic内の
preProcess()メソッド(事前処理メソッド)、finallyProcess()メソッド(最終実行メソッド)でDB接続とDB切断を行なっている為、
ビジネスロジック実装者はDBとの接続、切断を意識する必要がありません。(手動実行不要)
親クラスのAppBaseBlogic内でDBAccessクラスはdbaというインスタンス名で定義されており、ビジネスロジック内で自由に使用出来ます

**親クラスのAppBaseBlogic実装内容抜粋**

~~~
public class AppBaseBlogic<T extends AppBaseBean> extends BaseBlogic<T> {
    /** DBアクセスオブジェクト */
    protected DBAccess dba = null;
    
    @Override
    public boolean preProcess() throws Exception {
        super.preProcess();
        if (SystemConfigMng.isUseDatabaseFlg()) {
            openDB();
        }
        // 入力チェックエラー情報をクリア
        bean.initError();
        return true;
    }
 
    @Override
    public void finallyProcess() throws Exception {
        super.finallyProcess();
        // データベースコネクションをクローズ
        if (SystemConfigMng.isUseDatabaseFlg()) {
            closeDB();
        }
    }
    
    
    /**
     * DBオープンする。
     *
     * @throws Exception 例外
     */
    protected void openDB() throws Exception {
        try {
            if (dba == null) {
                dba = new DBAccess();
            }
            dba.openDB();
        } catch (Exception e) {
            LogWriter.error(e);
            throw e;
        }
    }
    /**
     * DBクローズする。
     */
    protected void closeDB() {
        try {
            if (dba != null) {
                dba.closeDB();
                dba = null;
            }
        } catch (Exception e) {
            LogWriter.error(e);
        }
    }    
~~~

##SELECT SQL実行 

例としてuser_id(ユーザID)、user_name(ユーザ名)等のカラムを持つuser_mst(ユーザマスタ)テーブルの情報を取得し
UserContext(ユーザ情報)というコンテキストクラスに情報を格納する場合の手順は以下になります。 

**検索結果を格納するコンテキストクラスを用意する**
コンテキストクラスはSerializableインターフェースを継承宣言する必要があります。 

~~~
package sample.context;
import java.io.Serializable;
/**
 * ユーザ情報格納コンテキストクラス
 */
public class UserContext implements Serializable {
    /**  ユーザID   */
    private String userId;
    /**  ユーザ名   */
    private String userName;
    /**  E-mail   */
    private String email;
    public String getUserId() {
        return userId;
    }
    public String getUserName() {
        return userName;
    }
    public String getEmail() {
        return email;
    }
    public void setUserId(String value) {
        userId = value;
    }
    public void setUserName(String value) {
        userName = value;
    }
    public void setEmail(String value) {
        email = value;
    }
}
~~~

**SELECT文を実行する**
com.bee_wkspace.labee_fw.common.db.DBAccessクラスのインスタンスdbaを使用しSQLを実行します。 

~~~
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT ");
        sql.append("    user_id,user_name,e_mail ");
        sql.append(" FROM ");
        sql.append("    user_mst ");
        sql.append(" WHERE ");
        sql.append("    user_id=?");
        sql.append(" AND ");
        sql.append("    e_mail=? ");
        dba.setSQL(sql);
        int idx = 1;
        dba.bind(idx++, "A0001");
        dba.bind(idx++, "test@testtest.com");
        UserContext context = null;
        RowTable rowTable = dba.execute();
        if (rowTable.getSize() != 0) {
            context = new UserContext();
            ContextSetter.set(context, rowTable.getRowColumn(0));
        }
~~~

- 2～10行目 文字列バッファにSQL構文を構築します。where文の条件値には?を設定し、後でバインド設定します。
- 12～15行目 SQL文をdbaにセットし、where条件のバインド値に実際の値を設定します、バインドインデックスは1から設定します。
- 18行目 SELECT文のSQLを実行し、検索結果テーブルcom.bee_wkspace.labee_fw.common.db.RowTableを取得します。
- 21行目 検索結果の1個目(0行目)データをcom.bee_wkspace.labee_fw.common.ContextSetterを使用してUserContextのインスタンス
contextにセットします。
- ContextSetterは検索結果カラム名と同じ名のセッターが存在する場合、又はカラム名のアンダーバーを除いた、後ろの1文字目を大文字に変換した名のセッターに持つコンテキストを引数で受けると、自動的にセッターを実行し、コンテキストに結果データをセットします。

**コンテキストを使用しない場合**
コンテキストを使用せずに直接カラムデータを取得する場合は以下の様に行ないます(抜粋) 

~~~
   
        RowTable rowTable = dba.execute();
        if (rowTable.getSize() != 0) {
            RowColumn column = rowTable.getRowColumn(0);
            String userId = column.getString("user_id");            
            String userName = column.getString("user_name");            
            String email = column.getString("e_mail");            
        }
~~~

- 4行目 rowTableから指定行(0個目)のカラム情報com.bee_wkspace.labee_fw.common.db.RowColumnを取得します。
- 5～7行目 columnから指定したカラム名の結果データを取得します。 


##INSERT SQL実行
INSERT文を実行するにはcom.bee_wkspace.labee_fw.common.db.UpdateHelperクラスを利用します。
UpdateHelperを使用するとINSERTのSQL文を作成する事なく内部的INSERTのSQL文を生成してINSERT実行出来ます。 

~~~
   
       try {
	       UpdateHelper helper = new UpdateHelper(UpdateHelper.INSERT, "user_mst");
	       helper.setParam("user_id", "B001");
	       helper.setParam("user_name", "テスト太郎");
	       helper.setParam("e_mail", "a@a.com");
	       dba.setSQL(helper.createSql());
	       int cnt = dba.executeUpdate();
	       dba.commit();
	       
	   } catch (SQLException e) {
	       dba.rollback();
	   }
~~~

- 3行目 引数にINSERTを示す定数と対象テーブル名を指定してUpdateHelperクラスのインスタンスを生成します。
- 4～6行目 インサートするカラム名と登録値をhelperに設定します。
- 7行目 INSERTのSQL文を生成してdbaオブジェクトにセットします。
- 8行目 INSERTを実行します、戻り値に登録件数を返します。
- 9行目 DBコネクションのコミットを実行します。
- 12行目 SQL実行時に例外が発生した場合はロールバックを実行すると安全です。 


##UPDATE SQL実行 
UPDATE文を実行するにはcom.bee_wkspace.labee_fw.common.db.UpdateHelperクラスを利用します。
UpdateHelperを使用するとUPDATEのSQL文を作成する事なく内部的UPDATEのSQL文を生成してUPDATE実行出来ます。 

~~~
       
           try {
               UpdateHelper helper = new UpdateHelper(UpdateHelper.UPDATE, "user_mst");
               helper.setParam("user_name", "テスト次郎");
               helper.setWhereCondition("user_id=? AND e_mail=?");
               
               dba.setSQL(helper.createSql());
               int idx = helper.bind(dba);
               dba.bind(idx++, "B001");
               dba.bind(idx++, "a@a.com");
               int cnt = dba.executeUpdate();
               dba.commit();
               
           } catch (SQLException e) {
               dba.rollback();
           }
     
~~~

- 3行目 引数にUPDATEを示す定数と対象テーブル名を指定してUpdateHelperクラスのインスタンスを生成します。
- 4行目 アップせーとするカラム名と更新値をhelperに設定します。
- 5行目 where条件をhelperに設定します(WHERE文言は不要)、カラム条件には?を設定して後でバインドします。
- 7行目 UPDATEのSQL文を生成してdbaオブジェクトにセットします。
- 8行目 バインドインデックスを取得します。
- 9～10行目 where条件のバインド部分に条件値をバインド設定する。
- 11行目 UPDATEを実行します、戻り値に更新件数を返します。
- 12行目 DBコネクションのコミットを実行します。
- 15行目 SQL実行時に例外が発生した場合はロールバックを実行すると安全です。 


###DELETE SQL実行 
DELETE文を実行するにはcom.bee_wkspace.labee_fw.common.db.UpdateHelperクラスを利用します。
UpdateHelperを使用するとDELETEのSQL文を作成する事なく内部的DELETEのSQL文を生成してDELETE実行出来ます。 

~~~
   
       try {
           UpdateHelper helper = new UpdateHelper(UpdateHelper.DELETE, "user_mst");
           helper.setWhereCondition("user_id=? AND e_mail=?");
           
           dba.setSQL(helper.createSql());
           int idx = helper.bind(dba);
           dba.bind(idx++, "B001");
           dba.bind(idx++, "a@a.com");
           int cnt = dba.executeUpdate();
           dba.commit();
           
       } catch (SQLException e) {
           dba.rollback();
       }
~~~

- 3行目 引数にUPDATEを示す定数と対象テーブル名を指定してUpdateHelperクラスのインスタンスを生成します。
- 4行目 where条件をhelperに設定します(WHERE文言は不要)、カラム条件には?を設定して後でバインドします。
- 6行目 DELETEのSQL文を生成してdbaオブジェクトにセットします。
- 7行目 バインドインデックスを取得します。
- 8～9行目 where条件のバインド部分に条件値をバインド設定する。
- 10行目 DELETEを実行します、戻り値に削除件数を返します。
- 11行目 DBコネクションのコミットを実行します。
- 14行目 SQL実行時に例外が発生した場合はロールバックを実行すると安全です。