Javaのinsertメソッド、updateメソッド、deleteメソッドの処理の流れ(後編)
Configuration の newStatementHandler 分析
SimpleExecutor の doUpdate メソッドは上記で分析されました:
1 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { 2 Statement stmt = null; 3 try { 4 Configuration configuration = ms.getConfiguration(); 5 StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); 6 stmt = prepareStatement(handler, ms.getStatementLog()); 7 return handler.update(stmt); 8 } finally { 9 closeStatement(stmt);10 }11 }
過去 2 日間で 5 行目の newStatementHandler メソッドを再読したところ、上記のメソッドが次であることがわかりました。このメソッドの分析は非常に簡単です。Configuration の newStatementHandler メソッドを見てみましょう。メソッドの実装は次のとおりです。
1 public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {2 StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);3 statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);4 return statementHandler;5 }
3 行目のコードは、興味深いものではありません。 2 行目のコードを見てください。StatementHandler インターフェイス実際にインスタンス化されるのは RoutingStatementHandler です。構築メソッドは次のように実装されます。
RoutingStatementHandler は、StatementHandler インターフェイスの実装でもあります。 StatementHandler インターフェイス参照デリゲートを保持します。ここでの StatementType は PREPARED であるため、7 行目の判定が実行されて PreparedStatementHandler がインスタンス化されます。インスタンス化プロセスは次のとおりです。
1 public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 2 3 switch (ms.getStatementType()) { 4 case STATEMENT: 5 delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); 6 break; 7 case PREPARED: 8 delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); 9 break;10 case CALLABLE:11 delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);12 break;13 default:14 throw new ExecutorException("Unknown statement type: " + ms.getStatementType());15 }16 17 }
- パラメータオブジェクト自体
- パラメータリスト
- 実行されるSQL文
ステートメントを生成する
Connection を生成するプロセスは上に書かれています。まず、SimpleExecutor の prepareStatement メソッドを投稿しましょう。 4 コードはステートメントを生成します。 4 行目のコードは、 1 protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 2 this.configuration = mappedStatement.getConfiguration(); 3 this.executor = executor; 4 this.mappedStatement = mappedStatement; 5 this.rowBounds = rowBounds; 6 7 this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 8 this.objectFactory = configuration.getObjectFactory(); 9 10 if (boundSql == null) { // issue #435, get the key before calculating the statement11 generateKeys(parameterObject);12 boundSql = mappedStatement.getBoundSql(parameterObject);13 }14 15 this.boundSql = boundSql;16 17 this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);18 this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);19 }
1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {2 Statement stmt;3 Connection connection = getConnection(statementLog);4 stmt = handler.prepare(connection, transaction.getTimeout());5 handler.parameterize(stmt);6 return stmt;7 }
コードの 6 行目はクエリのタイムアウトを設定し、コードの 7 行目は受信データのサイズを設定します。行 instantiateStatement メソッドの実装:
Statement prepare(Connection connection, Integer transactionTimeout)
行 2、boundSql から実際の SQL ステートメントを取得します。最初の部分は分析されています。 SQL ステートメントを取得した後、3 行目と 5 行目の判定を実行します。これは、Connection を通じてステートメントを取得するためのよく知られたコードです。PreparedStatement は、prepareStatement メソッドを通じて取得されます。これは PreparedStatement のサブクラスです。
Statement パラメータの設定
Statement を取得したら、次のステップはパラメータを設定するコードを確認するか、SimpleExecutor: の prepareStatement メソッドに戻ります。 1 public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { 2 ErrorContext.instance().sql(boundSql.getSql()); 3 Statement statement = null; 4 try { 5 statement = instantiateStatement(connection); 6 setStatementTimeout(statement, transactionTimeout); 7 setFetchSize(statement); 8 return statement; 9 } catch (SQLException e) {10 closeStatement(statement);11 throw e;12 } catch (Exception e) {13 closeStatement(statement);14 throw new ExecutorException("Error preparing statement. Cause: " + e, e);15 }16 }
1 protected Statement instantiateStatement(Connection connection) throws SQLException { 2 String sql = boundSql.getSql(); 3 if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) { 4 String[] keyColumnNames = mappedStatement.getKeyColumns(); 5 if (keyColumnNames == null) { 6 return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); 7 } else { 8 return connection.prepareStatement(sql, keyColumnNames); 9 }10 } else if (mappedStatement.getResultSetType() != null) {11 return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);12 } else {13 return connection.prepareStatement(sql);14 }15 }
1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {2 Statement stmt;3 Connection connection = getConnection(statementLog);4 stmt = handler.prepare(connection, transaction.getTimeout());5 handler.parameterize(stmt);6 return stmt;7 }
最终执行的是第26行的代码,从26行的代码我们可以知道,参数设置到最后都是通过参数的TypeHandler来执行的,JDBC为我们预定义了很多TypeHandler,比如int值的TypeHandler就是IntegerTypeHandler,当然我们也可以定义自己的TypeHandler,通常来说继承BaseTypeHandler就可以了。
但是在此之前,会获取到Statement(setParameters方法形参)、占位符位置号(for循环的遍历参数i)、参数值(通过属性名获取)与jdbcType(配置在配置文件中,默认为null),最终执行TypeHandler的setParameters方法,这是BaseTypeHandler中的一个方法:
1 public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { 2 if (parameter == null) { 3 if (jdbcType == null) { 4 throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters."); 5 } 6 try { 7 ps.setNull(i, jdbcType.TYPE_CODE); 8 } catch (SQLException e) { 9 throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +10 "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +11 "Cause: " + e, e);12 }13 } else {14 try {15 setNonNullParameter(ps, i, parameter, jdbcType);16 } catch (Exception e) {17 throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " +18 "Try setting a different JdbcType for this parameter or a different configuration property. " +19 "Cause: " + e, e);20 }21 }22 }
这里的参数不为null,走13行的else,执行setNonNullParameter方法,这是IntegerTypeHandler中的一个方法:
setNonNullParameter(PreparedStatement ps,
这里的代码就比较熟悉了,PreparedStatement的setInt方法。
执行更新操作并处理结果
最后一步,执行更新操作并对结果进行处理,回到SimpleExecuto的doUpdate方法:
1 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { 2 Statement stmt = null; 3 try { 4 Configuration configuration = ms.getConfiguration(); 5 StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); 6 stmt = prepareStatement(handler, ms.getStatementLog()); 7 return handler.update(stmt); 8 } finally { 9 closeStatement(stmt);10 }11 }
第6行已经准备好了Statement,第7行执行update操作并对结果进行处理并返回:
update(Statement statement)
这里的委托delegate前面已经说过了,其真实类型是PreparedStatementHandler,update方法的实现为:
1 public int update(Statement statement) throws SQLException {2 PreparedStatement ps = (PreparedStatement) statement;3 ps.execute();4 int rows = ps.getUpdateCount();5 Object parameterObject = boundSql.getParameterObject();6 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();7 keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);8 return rows;9 }
第3行的execute方法是PreparedStatement中的方法,execute方法执行操作,然后第4行通过getUpdateCount()方法获取本次操作更新了几条数据,作为最终的值返回给用户。
第5行的代码通过BoundSql获取参数对象,这里是MailDO对象,因为我们知道在插入场景下,开发者是有这种需求的,需要返回插入的主键id,此时会将主键id设置到MailDO中。
第6行的代码通过MappedStatement获取KeyGenerator,一个主键生成器。
第7行的代码做了一个操作完毕的后置处理:
<span style="color: #008080"> 1</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {</span><span style="color: #008080"> 2</span> <span style="color: #000000"> processBatch(ms, stmt, getParameters(parameter));</span><span style="color: #008080"> 3</span> <span style="color: #000000">}</span><span style="color: #008080"><br></span>
首先将对象包装成集合类型,然后跟第2行的代码processBatch方法:
1 public void processBatch(MappedStatement ms, Statement stmt, Collection<Object> parameters) { 2 ResultSet rs = null; 3 try { 4 rs = stmt.getGeneratedKeys(); 5 final Configuration configuration = ms.getConfiguration(); 6 final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 7 final String[] keyProperties = ms.getKeyProperties(); 8 final ResultSetMetaData rsmd = rs.getMetaData(); 9 TypeHandler<?>[] typeHandlers = null;10 if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) {11 for (Object parameter : parameters) {12 // there should be one row for each statement (also one for each parameter)13 if (!rs.next()) {14 break;15 }16 final MetaObject metaParam = configuration.newMetaObject(parameter);17 if (typeHandlers == null) {18 typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties, rsmd);19 }20 populateKeys(rs, metaParam, keyProperties, typeHandlers);21 }22 }23 } catch (Exception e) {24 throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);25 } finally {26 if (rs != null) {27 try {28 rs.close();29 } catch (Exception e) {30 // ignore31 }32 }33 }34 }
简单说这里就是遍历集合,通过JDBC4PreparedStatement的getGeneratedKeys获取ResultSet,然后从ResultSet中使用getLong方法获取生成的主键,设置到MailDO中。完成整个操作。
最后,本文演示的是insert数据的update方法流程,前文已经说过insert、update、delete在MyBatis中都是一样的,因此update、delete也是一样的操作,这里就不再赘述了。
以上がJavaのinsertメソッド、updateメソッド、deleteメソッドの処理の流れ(後編)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









トマト ノベルは非常に人気のある小説閲覧ソフトウェアです。トマト ノベルでは、新しい小説や漫画を読むことができます。どの小説も漫画もとても面白いです。小説を書きたい友達もたくさんいます。お小遣いを稼いで、小説の内容を編集することもできます。 「テキストに文章を書きたいです。それで、小説はどうやって書くのですか?友達は知らないので、一緒にこのサイトに行きましょう。小説の書き方の入門を少し見てみましょう。」 Tomato Novels を使用して小説を書く方法に関するチュートリアルを共有します。 1. まず、携帯電話で Tomato Free Novels アプリを開き、パーソナル センター - ライター センターをクリックします。 2. Tomato Writer Assistant ページに移動し、次の場所で [新しい本の作成] をクリックします。小説の終わり

Colorful マザーボードは中国国内市場で高い人気と市場シェアを誇っていますが、Colorful マザーボードのユーザーの中には、設定のために BIOS を入力する方法がまだ分からない人もいます。この状況に対応して、編集者はカラフルなマザーボード BIOS に入る 2 つの方法を特別に提供しました。ぜひ試してみてください。方法 1: U ディスク起動ショートカット キーを使用して、U ディスク インストール システムに直接入ります。ワンクリックで U ディスクを起動する Colorful マザーボードのショートカット キーは ESC または F11 です。まず、Black Shark インストール マスターを使用して、Black Shark インストール マスターを作成します。 Shark U ディスク起動ディスクを選択し、コンピュータの電源を入れます。起動画面が表示されたら、キーボードの ESC キーまたは F11 キーを押し続けて、起動項目を順次選択するウィンドウに入ります。「USB」の場所にカーソルを移動します。 」と表示され、その後

残念ながら、WeChat は広く使用されているソーシャル ソフトウェアであり、何らかの理由で特定の連絡先を誤って削除してしまうことがよくあります。ユーザーがこの問題を解決できるように、この記事では、削除された連絡先を簡単な方法で取得する方法を紹介します。 1. WeChat の連絡先削除メカニズムを理解します。これにより、削除された連絡先を取得できるようになります。WeChat の連絡先削除メカニズムでは、連絡先がアドレス帳から削除されますが、完全には削除されません。 2. WeChat の組み込みの「連絡先帳復元」機能を使用します。WeChat には、この機能を通じて以前に削除した連絡先をすばやく復元できる「連絡先帳復元」機能が用意されています。 3. WeChat 設定ページに入り、右下隅をクリックし、WeChat アプリケーション「Me」を開き、右上隅にある設定アイコンをクリックして設定ページに入ります。

携帯電話が人々の日常生活において重要なツールになるにつれて、フォント サイズの設定は重要なパーソナライゼーション要件になりました。さまざまなユーザーのニーズを満たすために、この記事では、簡単な操作で携帯電話の使用体験を向上させ、携帯電話のフォントサイズを調整する方法を紹介します。携帯電話のフォント サイズを調整する必要があるのはなぜですか - フォント サイズを調整すると、テキストがより鮮明で読みやすくなります - さまざまな年齢のユーザーの読書ニーズに適しています - フォント サイズを使用すると、視力の悪いユーザーにとって便利です携帯電話システムの設定機能 - システム設定インターフェイスに入る方法 - 設定インターフェイスで「表示」オプションを見つけて入力します。 - 「フォント サイズ」オプションを見つけて、サードパーティでフォント サイズを調整します。アプリケーション - フォント サイズの調整をサポートするアプリケーションをダウンロードしてインストールします - アプリケーションを開いて、関連する設定インターフェイスに入ります - 個人に応じて

テクノロジーの発展に伴い、モバイルゲームは人々の生活に欠かせないものになりました。かわいいドラゴンエッグの画像と面白い孵化過程で多くのプレイヤーの注目を集めており、その中でも注目を集めているゲームの一つがモバイル版ドラゴンエッグです。プレイヤーがゲーム内で自分のドラゴンをより適切に育成し成長させることができるように、この記事ではモバイル版でドラゴンの卵を孵化させる方法を紹介します。 1. 適切な種類のドラゴン エッグを選択する プレイヤーは、ゲーム内で提供されるさまざまな種類のドラゴン エッグの属性と能力に基づいて、自分に適したドラゴン エッグの種類を慎重に選択する必要があります。 2. 孵化機のレベルをアップグレードします。プレイヤーはタスクを完了し、小道具を収集することで孵化機のレベルを向上させる必要があります。孵化機のレベルは孵化速度と孵化成功率を決定します。 3. プレイヤーはゲームに参加する必要がある孵化に必要なリソースを収集します。

今日の社会において、携帯電話は私たちの生活に欠かせないものとなっています。私たちの日常のコミュニケーション、仕事、生活のための重要なツールとして、WeChat はよく使用されます。ただし、異なるトランザクションを処理する場合は 2 つの WeChat アカウントを分離する必要がある場合があり、そのためには携帯電話が 2 つの WeChat アカウントへの同時ログインをサポートする必要があります。有名な国内ブランドとして、ファーウェイの携帯電話は多くの人に使用されていますが、ファーウェイの携帯電話で 2 つの WeChat アカウントを開設する方法は何でしょうか?このメソッドの秘密を明らかにしましょう。まず、Huawei 携帯電話で 2 つの WeChat アカウントを同時に使用する必要があります。最も簡単な方法は次のとおりです。

Go 言語のメソッドと関数の違いは、構造との関連付けにあります。メソッドは構造に関連付けられ、構造データまたはメソッドを操作するために使用されます。関数は型に依存せず、一般的な操作を実行するために使用されます。

スマートフォンの普及に伴い、携帯フィルムは欠かせないアクセサリーの一つとなりました。耐用年数を延ばすには、携帯電話の画面を保護する適切な携帯電話フィルムを選択してください。この記事では、読者が自分に最適な携帯電話フィルムを選択できるように、携帯電話フィルムを購入する際のいくつかのポイントとテクニックを紹介します。携帯電話フィルムの素材と種類を理解する:PET フィルム、TPU など。 携帯電話フィルムは強化ガラスを含むさまざまな素材でできています。 PETフィルムは比較的柔らかく、強化ガラスフィルムは耐傷性に優れ、TPUは耐衝撃性能に優れています。選択する際は、個人の好みやニーズに基づいて決定できます。画面の保護の程度を考慮してください。携帯電話のフィルムの種類によって、画面の保護の程度も異なります。 PETフィルムは主に傷防止の役割を果たしますが、強化ガラスフィルムは落下耐性に優れています。より良いものを選ぶことができます
