スプリング)バインドDB-1


多くのWebアプリケーションは、DBMSを使用してデータを格納します.
JavaはJDBC APIを使用するか、JPA、MyBasisなどの技術を使用してDBバインディングを処理する.
ここでは、SpringがJDBCに提供するJDbcTemplateについて説明します.
JDBCプログラミングの欠点を補うスプリング
JDBC APIを使用すると、データベースバインディングに必要な接続を取得し、クエリーを実行するためのPrepared Statementを生成できます.その後、クエリーを実行した後、PreparedStatement、Connectionなどを閉じます.
ここでは実際のコアコードはあまりなく,実際にはデータ処理とは無関係であるが,JDBCプログラミングでは構造的に重複するコードが発生する可能性がある.
このような構造上の重複を低減するために,Template法モードとStrategyモードを併用することができ,Springはこれら2つのモードを組み合わせたJdbcTemplateクラスを提供する.
💡Template Methodモードとは?
  • モード
  • は、あるタスクを処理する一部をサブクラスにカプセル化し、タスク全体を実行する構造を変更することなく、特定のフェーズで実行された履歴を変更する.
  • は、同じ部分の異なる構文からなる方法のコード重複を低減するのに非常に有用である.
  • 💡戦略モデルとは?
  • は、各オブジェクトの可能な動作についてポリシークラスを作成し、類似の動作をカプセル化するインタフェースを定義することによって、その動作を直接修正するのではなく、オブジェクトの動作を動的に変更することによって、動作を柔軟に拡張する方法
  • を提供する.
  • 、すなわち、オブジェクトが実行可能な各動作をポリシーに設定するモード
  • です.動作を動的に変更する必要がある場合は、ポリシーを変更するだけで動作を変更できます.
    💡@トランザクション宣言
    JDBC APIを使用してトランザクションを処理する場合は、自動コミットを無効にし、トランザクションを個別にコミットまたはロールバックする必要がありますが、スプリングを使用する場合は、トランザクションを適用する方法に@Transactionalコメントを追加するだけです.
    提出とロールバック箇所理由スプリング自己処理😎
    接続プール
    1.ネットの意味とは?
    実際のサービス運用環境では、javaプログラムとDBMSを異なるデバイスで実行し、javaプログラムからDBMSまでインタフェースを生成する時間がコンピュータにとって長く、パフォーマンスに影響します.また、同時に接続するユーザ数が増えると、ユーザごとにDB接続が作成され、DBMSに負荷がかかります.
    このとき,最初の接続による応答速度の低下と同時に接続者が多い場合に生じる負荷を低減するために,接続プールを用いた.
    接続プール
  • は、予め一定数のDB接続を作成する方法である.
    コネクタを使用すると、コネクタの作成時間を節約できます.
  • の同時接続数が増加しても、接続を作成する負荷が減少するため、より多くの同時接続を処理できます.
  • インタフェースも一定数保持でき、DBMSの負荷を一定レベルに保つことができる.
  • 従って、実際のサービス運用環境では、接続プールを用いてDB接続を管理し、DB接続プール機能を提供するモジュールとしては、Tomcat JDBC、HikariCP、DBPP、c 3 p 0等がある.
    現在、継続的な開発、性能等を考慮して、Tomcat JDBCまたはHikariCPが推奨されている.
    💡注意!
    コネクタプールで作成したコネクタは、引き続き繰り返し使用されます.
    1つの接続は永遠に維持されるものではありません.
    DBMS設定により、一定時間クエリーを実行しないと接続が切断されます.この場合、コネクタの接続は切断されていますが、コネクタはプールにあります.
    この状態で、コネクタをプールからインポートして使用すると、接続が切断されたコネクタであるため、エクスポートが発生します.オフィスシステムのように、特定の時間帯にユーザーが発生しない可能性があります.
    🤔 どうすればいいの?
    接続プールの接続が有効かどうかを定期的にチェックします.
    データソース設定
    JDBC APIは、ドライバマネージャに加えて、データソースを使用してDB接続を取得する方法を定義します.
    Springが提供するDBバインド機能は、データソースを使用してDB接続を取得し、DBバインドに使用するデータソースをspringbineとして登録し、DBバインドを実現する空のオブジェクトがデータソースに注入されます.
    JdbcTemplateを使用したクエリーの実行
    スプリングを使用すると、データ・ソースまたは接続、Statement、ResultSetを直接使用することなく、JdbcTemplateを使用してクエリーを簡単に実行できます.
    サンプルコードとともに表示します.
    1.JdbcTemplateの作成
    package spring;
    
    import javax.sql.DataSource;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    
    public class MemberDao {
        private JdbcTemplate jdbcTemplate;
        
        public MemberDao(DataSource dataSource) {
        	this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
        
        ...
    }
    JdbcTemplateオブジェクトを作成するには、データソースをジェネレータに渡すだけです.
    JdbcTemplateを生成するコードをMemberDaoクラスに追加しました.
    次に、スプリング設定クラスにMemberDao空の設定を追加します.
    @Configuration
    public class AppCtx {
    
        @Bean(destroyMethod = "close")
        public DataSource dataSource() {
            DataSource ds = new DataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8");
            ds.setUserName("spring5");
            ds.setPassword("spring5");
            ... // 생략
            return ds;
        }
        
        @Bean
        public MemberDao memberDao() {
            return new MemberDao(dataSource());
        }
    }
    2.JdbcTemplateを使用してクエリーを実行する
    JdbcTemplateクラスはSELECTクエリを実行するquery()メソッドを提供します.
    一般的なクエリー方法は次のとおりです.
  • List< T > query(String sql, RowMapper< T > rowMapper)
  • List< T > query(String sql, Object[] args , RowMapper< T > rowmapper)
  • List< T > query(String sql, RowMapper< T > rowmapper, Object...args)
  • query()メソッドは、sqlパラメータに渡されるクエリを実行し、RowMapperを使用してResultSetの結果をJavaオブジェクトに変換します.sqlパラメータがインデックスベースのパラメータクエリの場合、argsパラメータを使用して各インデックスパラメータの値を指定します.
    RowMapperインタフェース
    package org.springframework.jdbc.core;
    
    public interface RowMapper< T > {
        T mapRow(ResultSet rs, int rowNum) throws SQLException;
    }
    RowMapperのmapRow()メソッドはmapper機能を実現し,SQL実行結果から求めたResultSetから1行のデータを読み出してJavaオブジェクトに変換できる.
    RowMapperインタフェースを実装するクラスを記述することもできますが、RowMapperオブジェクトを任意のクラスまたはラムダ式で作成してqueryメソッドに渡すことも多いです.
    次に、「任意のクラス」(Member)を使用する例を示します.
    public Member selectByEmail(String email) {
            List<Member> results = jdbcTemplate.query(
                    "select * from MEMBER where EMAIL = ?",
                    new RowMapper<Member>() {
                        @Override
                        public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
                            Member member = new Member (
                                rs.getString("EMAIL"),
                                rs.getString("PASSWORD"),
                                rs.getString("NAME"),
                                rs.getTimestamp("REGDATE").toLocalDateTime());
                            member.setId(rs.getLong("ID"));
                            return member;
                        }
                    },
                    email);
    
            return results.isEmpty() ? null : results.get(0);
    }
    同じRowMapperインプリメンテーションを複数の場所で使用する場合は、コードの重複を回避するために、RowMapperインタフェースをインプリメンテーションするクラスを作成できます.
    public class MemberRowMapper implements RowMapper<Member> {
    	public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
            	Member member = new Member (
                	rs.getString("EMAIL"),
                	rs.getString("PASSWORD"),
                	rs.getString("NAME"),
                	rs.getTimestamp("REGDATE").toLocalDateTime());
           	member.setId(rs.getLong("ID"));
           	return member;
        }
    }
    
    // MemberRowMapper 객체 생성
    List<Member> results = jdbcTemplate.query(
    	"select * from MEMBER where EMAIL = ? and NAME = ?",
        new MemberRowMapper(),
        email, name);
    💡 QueryForObject()メソッド
    QueryForObject()メソッドは、クエリの実行結果が1行しかない場合に>を使用します.(例えば、MEMBERからcount(*))を選択)
    このメソッドでは、クエリーでインデックスパラメータを使用することもできます.インデックス・パラメータがある場合は、パラメータ値を可変パラメータに渡します.
    実行結果に2つ以上のコラムがある場合は、rowmapperをパラメータに渡すことで結果を生成できます.
    3.JdbcTemplateを使用した変更クエリー
    INSERT、UPDATE、DELETEクエリはupdate()メソッドを使用します.
  • int update(String sql)
  • int update(String sql, Object... args)
  • update()メソッドは、クエリの実行結果によって変更されたローの数を返します.
    Ex.
    	jdbcTemplate.update(
        	   "update MEMBER set NAME = ?, PASSWORD = ? where EMAIL = ?",
                member.getName(), member.getPassword(), member.getEmail());
    4.PreparedStatementCreatorを使用したクエリーの実行
    上記のupdate()メソッドの例から、インデックスパラメータをそれぞれ渡す値が表示されます.ほとんどの場合、この方法でクエリーのインデックス・パラメータ値を渡すことができます.
    ただし、ここでは、PreparedStatementのsetメソッドを使用してインデックスパラメータの値を直接設定する必要がある場合があります.この場合、PreparedStatementCreatorをパラメータとする方法を使用して、PreparedStatementを直接作成および設定する必要があります.
    PreparedStatementCreatorインタフェース
    package org.springframework.jdbc.core;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    public interface PreparedStatementCreator {
    	PreparedStatement createPreparedStatement(Connection conn) 
        throws SQLException;
    }
    PreparedStatementCreatorインタフェースのcreatePreparedStatement()メソッドにはConnectionタイプのパラメータがあります.
    PreparedStatementCreatorを実装するクラスでは、上記のメソッドのパラメータで渡されたConnectionを使用してPreparedStatementオブジェクトを作成し、インデックスパラメータを設定して戻ります.
    5.INSERTクエリの実行時にKeyHolderを使用して生成キー値を自動的に取得する
    MySQLのAUTO_INCREMENTコラムは、行を追加すると自動的に値の割り当てが増加するコラムです.したがって、INSERTクエリ文の作成時に値は指定されません.
    しかし、クエリーの実行後に生成されるキー値を知りたい場合は、どうすればいいですか?
    JdbcTemplateは、この点を理解する方法を提供しています.
    KeyHolderを使います!
    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(new PreparedStatementCreator() { 
    	... 
        PreparedStatement pstmt = connection.preparedStatement(
        	"insert into ..."
            , new String[] {"ID"} );
            
            ...
            
    }, keyHolder);
  • ConnectionのPreparedStatement()メソッドを使用してPreparedStatementオブジェクトを作成する場合は、2番目のパラメータStringスキーム(自動生成キーバー)を使用してキーバーリストを自動的に生成し、
  • を指定します.
  • JdbcTemplate.update()メソッドの2番目のパラメータKeyHolderオブジェクトを渡すと、キー値がKeyHolderオブジェクトに渡されて保存されます.
  • KeyHolderに保存されているキー値はgetKey()メソッドで取得できます.
    DB連動記事-続き2...
    リファレンス
    テンプレートメソッドモードhttps://gmlwjd9405.github.io/2018/07/13/template-method-pattern.html
    戦略モデルhttps://victorydntmd.tistory.com/292