Mybatis 面接でよくある質問30選(回答付き2023年最新版)

1.MyBatisとは何ですか? MyBatisはどのように機能しますか? MyBatisの利用シーンはどのようなものですか?

MyBatis は、優れた永続層フレームワークです。Java 言語に基づく ORM フレームワークです。XML または注釈を通じてデータベース内の Java オブジェクトとテーブルをマップし、永続操作を実装します。

MyBatis は、ORM (オブジェクト リレーショナル マッピング) およびデータ アクセス操作の実装に使用できる優れた Java 永続性フレームワークです。

mybatis の仕組み:
mybatis 構成ファイルには、Mybatis グローバル構成ファイルと Mybatis マッピング ファイルが含まれています。グローバル構成ファイルはデータ ソース、トランザクション、その他の情報を構成し、マッピング ファイルは SQL 実行に関連する情報を構成します。

Mybatis は、構成ファイル情報 (グローバル構成ファイルとマッピング ファイル) を読み取ることによって、セッション ファクトリである SqlSessionFactory を構築します。

SqlSessionFactory を通じて、SqlSession またはセッションを作成できます。

Mybatis は SqlSession を通じてデータベースを操作します。SqlSession 自体はデータベースを直接操作できず、基盤となる Executor エグゼキューター インターフェイスを通じてデータベースを操作します。

Executor インターフェイスには 2 つの実装クラスがあり、1 つは通常の Executor、もう 1 つはキャッシュ Executor (デフォルト) です。Executor エグゼキュータによって処理される SQL 情報は、基礎となるオブジェクト MappedStatement にカプセル化されます。

MyBatis は、次のシナリオで広く使用されています。

1.データベース アクセス操作: MyBatis は柔軟な SQL ステートメントの記述とカスタマイズされた SQL マッピングを提供し、SQL ステートメントの実行をよりきめ細かい方法で制御できるため、データベース上で複雑な操作が必要なシナリオに適しています。

2.大量のデータ操作: MyBatis のバッチ操作とページング クエリ機能は、大量のデータへのアクセスと操作を非常にうまく処理できるため、大量のデータに対する操作が必要なシナリオに適しています。

3.高い同時アクセス: MyBatis のキャッシュ メカニズムは、データベース アクセスの数を効果的に削減し、システムの同時実行機能を向上させることができるため、高い同時アクセスをサポートする必要があるシナリオに適しています。

4.データベース トランザクション処理: MyBatis はトランザクション処理メカニズムをサポートし、複数の操作でトランザクション管理を実行できるため、データベース トランザクション処理が必要なシナリオに適しています。

5.マルチデータソース操作:MyBatis は複数のデータソースの操作をサポートし、複数のデータベースに同時に接続して操作できるため、複数のデータベースの同時操作が必要なシナリオに適しています。
要約すると、MyBatis は、データベース アクセスと ORM 操作を必要とするさまざまなシナリオ、特に高い同時実行性、大量のデータ、および複雑な操作を必要とするシナリオで広く使用できます。

2. MyBatis の利点は何ですか?

MyBatis には次の利点があります。

1.高い柔軟性: MyBatis は、さまざまなニーズを満たす豊富なマッピング ステートメントと柔軟な構成を提供します。

2.習得が簡単: MyBatis は比較的スムーズに学習でき、比較的簡単に始めることができます。

3.パフォーマンスの向上: MyBatis は、SQL ステートメントと結果セットをキャッシュすることにより、システムのパフォーマンスを向上させることができます。

4. SQL を自由に制御できる: M​​yBatis は、複雑な SQL ステートメントを構築するための動的 SQL の使用をサポートしており、SQL の実行を自由に制御できます。

5.統合が簡単: MyBatis は Spring などのフレームワークと統合できるため、他のフレームワークでも簡単に使用できます。

つまり、MyBatis は、さまざまな Java プロジェクトで広く使用されている、強力で使いやすく、パフォーマンスに優れた ORM フレームワークです。

3. MyBatis はどのように機能しますか?

MyBatis の動作原理は、次の 3 つのステップに簡単に要約できます。

1. SqlSessionFactoryBuilder を通じて SqlSessionFactory オブジェクトを作成します。

2. SqlSessionFactory オブジェクトの openSession メソッドを使用して SqlSession オブジェクトを作成します。

3. SQL ステートメントの実行、トランザクションの送信など、SqlSession オブジェクトを通じてデータベースを操作します。

MyBatis のワークフローは次のとおりです。

1. データベース接続情報、マッピング ファイルの場所などを含む MyBatis 構成ファイルをロードします。

2. 設定ファイルを解析し、MyBatis の設定情報を保存するための Configuration オブジェクトを作成します。

3. SqlSessionFactory オブジェクトの作成 SqlSessionFactory はスレッド セーフ オブジェクトであり、SqlSession オブジェクトの作成に使用されるファクトリです。

4. SqlSession オブジェクトを作成します。SqlSession は MyBatis のコア オブジェクトです。SQL ステートメントの実行に使用されます。SqlSession オブジェクトはデータベース接続を表します。

5. SqlSession オブジェクトを通じて、クエリ、挿入、更新、削除、その他の操作を含む SQL ステートメントを実行します。

6. 必要に応じて、トランザクションを送信します。

7. SqlSession オブジェクトを閉じ、リソースを解放します。

ワークフロー全体を通じて、MyBatis は Configuration オブジェクトを通じてさまざまな構成情報を保存し、SqlSessionFactory オブジェクトを通じて SqlSession オブジェクトを作成し、SqlSession オブジェクトを通じて SQL ステートメントを実行し、最後にデータベースとの対話を実現します。

4. MyBatis のコアコンポーネントは何ですか?

MyBatis のコア コンポーネントには次のものが含まれます。

1.構成: MyBatis 構成クラス。データベース接続情報、マッピング ファイルの場所、キャッシュ構成などを含む MyBatis 構成情報を保存するために使用されます。

2. SqlSessionFactory : SqlSessionFactory はスレッド セーフ オブジェクトであり、SqlSession オブジェクトの作成に使用されるファクトリであり、Configuration オブジェクトやデータ ソースなどの情報が含まれています。

3. SqlSession : SqlSession は MyBatis のコア オブジェクトであり、SQL ステートメントの実行に使用されます。SqlSession オブジェクトはデータベース接続を表します。SqlSession は、クエリ操作、挿入操作、更新操作、削除操作など、データベースを操作するための一連のメソッドを提供します。

4. Executor : Executor は MyBatis の Executor であり、SQL ステートメントの実行を担当します。

MyBatis は、SimpleExecutor、ReuseExecutor、および BatchExecutor の 3 つのエグゼキューターを提供します。これらはそれぞれ、単純なステートメントの実行、再利用されたプリペアドステートメントの実行、およびバッチ実行に使用されます。

5. StatementHandler : StatementHandler は JDBC ステートメントを処理するために使用されるインターフェイスであり、MyBatis は StatementHandler インターフェイスを実装することによって JDBC ステートメントの操作をカプセル化します。

6. ParameterHandler : ParameterHandler は JDBC ステートメントのパラメーターを処理するために使用され、MyBatis は ParameterHandler インターフェイスを実装することによって SQL ステートメント内のパラメーターを処理します。

7. ResultSetHandler : ResultSetHandler は JDBC ResultSet を処理するために使用されるインターフェースであり、MyBatis は ResultSetHandler インターフェースを実装することによって JDBC ResultSet の操作をカプセル化します。

8. TypeHandler : TypeHandler は、Java オブジェクトと JDBC 型の間の変換を処理するために使用されます。MyBatis は、さまざまな型の変換を処理するための豊富な TypeHandler を提供します。

5. MyBatis の動的 SQL とは何ですか? 動的 SQL を使用するにはどうすればよいですか?

MyBatis の動的 SQL には次のものが含まれます。

if要素: if要素により条件判定を実現し、条件に応じて異なるSQL文を生成できます。例えば:

<select id="findUserById" parameterType="int" resultType="User">
    select * from user where 1 = 1
    <if test="id != null">
        and id = #{id}
    </if>
    <if test="username != null">
        and username = #{username}
    </if>
</select>

Where 要素: Where 要素は、複数の条件を結合するために使用されます。最初の条件が true の場合は、「WHERE」キーワードが結合され、それ以外の場合は、「AND」キーワードが結合されます。例えば:

<select id="findUser" parameterType="User" resultType="User">
    select * from user
    <where>
        <if test="id != null">
            id = #{id}
        </if>
        <if test="username != null">
            and username = #{username}
        </if>
    </where>
</select>

Choose 要素: Choose 要素は Java の switch ステートメントに似ており、実行するブランチを選択するために使用されます。例えば:

<select id="findUser" parameterType="User" resultType="User">
    select * from user
    <where>
        <choose>
            <when test="id != null">
                and id = #{id}
            </when>
            <when test="username != null">
                and username = #{username}
            </when>
            <otherwise>
                and 1 = 1
            </otherwise>
        </choose>
    </where>
</select>

Set 要素: Set 要素は更新操作に使用され、更新ステートメントのフィールドは Set 要素を通じて動的に設定できます。例えば:

<update id="updateUser" parameterType="User">
    update user
    <set>
        <if test="username != null">
            username = #{username},
        </if>
        <if test="password != null">
            password = #{password},
        </if>
    </set>
    where id = #{id}
</update>

Foreach 要素: Foreach 要素は、コレクションをループし、複数の SQL ステートメントを生成するために使用されます。例えば:

<select id="findUsersByIdList" parameterType="List" resultType="User">
    select * from user where id in
    <foreach item="id" collection="list" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

動的 SQL により、さまざまな条件に基づいてさまざまな SQL ステートメントを生成できるため、より柔軟で効率的なデータベース操作が実現します。

6. MyBatis のキャッシュメカニズムは何ですか? キャッシュにはどのような種類がありますか?

MyBatis のキャッシュ機構は、SQL 文を実行するとクエリ結果をキャッシュし、次回同じ SQL 文を実行するときはキャッシュから直接結果を取得するため、クエリ効率が向上します。MyBatis のキャッシュ メカニズムは、1 次キャッシュと 2 次キャッシュの 2 つのタイプに分かれています。

1. レベル 1 キャッシュ

第 1 レベルのキャッシュは、MyBatis の SqlSession レベルのキャッシュを指します。つまり、同じ SQL ステートメントが同じ SqlSession で実行されると、結果は 2 番目のクエリ中にキャッシュから直接取得されます。

1 次キャッシュのデフォルトの開き方は、SqlSessionFactory のデフォルト値によって構成されます。これは、mybatis-config.xml ファイル内のタグを構成することでオンまたはオフにできます。

例えば:

<settings>
    <setting name="localCacheScope" value="SESSION"/>
</settings>

1 次キャッシュのキャッシュ スコープは SqlSession レベルです。つまり、同じ SqlSession 内のすべての操作が同じキャッシュを共有します。

一次キャッシュのキャッシュ障害状況には次のようなものがあります。

(1) SqlSession が閉じられる;
(2) 追加、削除、および変更操作が実行される;
(3) キャッシュのクリア操作が実行される;
(4) SqlSession で明示的に clearCache メソッドが呼び出される。

2. 2次キャッシュ

2 次キャッシュは、MyBatis のマッパー レベル キャッシュを指します。つまり、同じ SQL ステートメントが複数の SqlSession で実行される場合、結果は 2 番目のクエリ中にキャッシュから直接取得されます。

2 次キャッシュのデフォルトのアクティブ化は、Mapper のキャッシュ構成によって実現され、Mapper.xml ファイル内のタグを構成することで有効または無効にできます。

例えば:

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

2 次キャッシュのキャッシュ スコープはマッパー レベルです。つまり、同じマッパーのすべての SqlSession が同じキャッシュを共有します。

2 次キャッシュのキャッシュ障害状況には、次のようなものがあります。

(1) 追加、削除、および変更操作が実行されます。
(2) キャッシュのクリア操作が実行されます。
(3) Mapper.xml ファイル内のタグで、キャッシュの更新間隔を示す flashInterval 属性が構成されます。
(4) Mapper.xmlファイルのタグ内にキャッシュの最大容量を示すsize属性が設定されており、キャッシュ数が最大容量を超えた場合、キャッシュクリア操作がトリガされます (5)明示的にclearCacheメソッドが呼び出されますSqlSession で

MyBatis のキャッシュ アルゴリズムには次のものが含まれます

LRU (最も最近使用されていない) : 最も最近使用されていないキャッシュ アルゴリズムこのアルゴリズムは、タグ内のエビクション属性を構成することで選択できます。

FIFO (先入れ先出し) : 先入れ先出しキャッシュ アルゴリズム。タグ内のエビクション属性を構成することで選択できます。

SOFT : ソフト参照キャッシュ アルゴリズム。タグの type 属性を SOFT に設定することでこのアルゴリズムを選択できます。

WEAK : 弱い参照キャッシュ アルゴリズム。タグ内の type 属性を WEAK に設定することでこのアルゴリズムを選択できます。

NONE : キャッシュを使用しません。タグの type 属性を NONE に設定することで、このアルゴリズムを選択できます。

つまり、MyBatis のキャッシュ メカニズムはクエリ効率を効果的に向上させることができますが、ダーティ データを避けるためにキャッシュの失敗に注意する必要があります。

同時に、さまざまなビジネス シナリオに応じて、さまざまなキャッシュ タイプを選択して、キャッシュ効果を最適化できます。

7. MyBatis のプラグインの仕組みは何ですか? プラグインはどのように書くのでしょうか?

MyBatis のプラグイン メカニズムは、SQL ステートメントを実行する MyBatis のさまざまなステージにカスタム ロジックを挿入して、MyBatis の機能を拡張または変更できる拡張メカニズムです。

MyBatis のプラグイン機構には主に以下のインターフェースが含まれています。

Interceptor : Interceptor は、MyBatis プラグインのコア インターフェイスです。すべてのプラグインは、このインターフェイスを実装する必要があります。Interceptor では、intercept、plugin、setProperties、getProperties の 4 つのメソッドが定義されています。

Executor : Executor は MyBatis のエグゼキュータであり、SQL ステートメントを実行するために使用されます。

MyBatis は、SimpleExecutor、ReuseExecutor、BatchExecutor の 3 つのエグゼキュータを提供します。エグゼキュータは、クエリ、更新など、インターセプタによってインターセプトできるいくつかのメソッドを定義します。

ParameterHandler : ParameterHandler は、JDBC ステートメントのパラメーターを処理するために使用され、インターセプターによってインターセプトすることもできます。

ResultSetHandler : ResultSetHandler は、JDBC ResultSet インターフェイスを処理するために使用され、Interceptor によってインターセプトすることもできます。

StatementHandler : StatementHandler は、JDBC ステートメントを処理するために使用されるインターフェイスであり、インターセプターによってインターセプトすることもできます。

MyBatis プラグインを作成する手順は次のとおりです。

1. Interceptor インターフェイスを実装し、カスタム ロジックを挿入できる intercept メソッドを実装します。

2. プラグイン メソッドを実装します。このメソッドは、元のオブジェクトと Interceptor オブジェクトのロジックを含むプロキシ オブジェクトを返すために使用され、元のオブジェクトのメソッド呼び出しをインターセプトするために使用されます。

3. mybatis-config.xml でプラグインを構成し、Interceptor 実装クラスを plugins ノードに追加します。

簡単なプラグインの実装例を次に示します。

@Intercepts({
    
    
    @Signature(type = Executor.class, method = "update", args = {
    
    MappedStatement.class, Object.class})
})
public class MyPlugin implements Interceptor {
    
    
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    
    
        // 在执行update方法前,输出日志
        System.out.println("Before executing update method.");
        Object result = invocation.proceed();
        // 在执行update方法后,输出日志
        System.out.println("After executing update method.");
        return result;
    }
    
    @Override
    public Object plugin(Object target) {
    
    
        // 生成代理对象
        return Plugin.wrap(target, this);
    }
    
    @Override
    public void setProperties(Properties properties) {
    
    
        // 设置插件属性
    }
}

上の例では、MyPlugin クラスを定義し、Interceptor インターフェイスを実装し、intercept、plugin、および setProperties メソッドをオーバーライドしました。

アノテーション @Intercepts はインターセプトされたオブジェクトとメソッドをマークするために使用され、@Signature はインターセプトされたメソッドのパラメーター タイプをマークするために使用されます。

intercept メソッドでは、update メソッドの実行前後にログを出力するなどのカスタムロジックを挿入できます。

プラグイン メソッドでは、プロキシ オブジェクトを生成し、そのプロキシ オブジェクトを返します。

setProperties メソッドでは、プラグインのプロパティを設定できます。

プラグインの作成が完了したら、mybatis-config.xml ファイルでプラグインを構成する必要があります。

例えば:

<plugins>
    <plugin interceptor="com.example.MyPlugin">
        <property name="property1" value="value1"/>
        <property name="property2" value="value2"/>
    </plugin>
</plugins>

上記の構成では、MyPlugin クラスをプラグインのインターセプターとして使用し、タグを通じてプラグインのプロパティを設定します。

つまり、MyBatis のプラグイン メカニズムは、ロギング、キャッシュ、ページングなど、カスタマイズされたプラグインを通じて独自の機能の一部を実装できる、非常に柔軟な拡張メカニズムです。

8. MyBatis のページング方法は何ですか? ページングを実装するにはどうすればよいですか?

MyBatis には、パラメータ ベースのページング、MyBatis 物理ページング プラグインに基づくページング、MyBatis 論理ページング プラグインに基づくページング、データベース ベースのページング、およびアプリケーション ベースのページングの 5 つのページング方法があります。

1.制限ステートメントに基づくページング方法:

优点:实现简单,适用于简单的分页查询;

缺点:对于复杂的查询SQL可能存在问题。

2.物理ページング プラグインに基づくページング方法:

优点:支持多种数据库的分页查询,分页效果较好;

缺点:需要手动配置插件,对于不同的数据库需要选择不同的插件。

3. RowBounds に基づくページング方法:

优点:实现简单,可以很好的支持分页;

缺点:需要手动计算起始位置和分页大小,对于复杂的分页查询比较麻烦。

4. MyBatis-Plus に基づくページング方法:

优点:MyBatis-Plus提供了丰富的分页查询方法,使用方便;

缺点:需要引入MyBatis-Plus依赖,不太适合只使用MyBatis的项目。

5.カスタム プラグインに基づくページング方法:

优点:灵活性高,可以根据需求定制分页规则;

缺点:需要编写插件代码,实现相对复杂。

一般に、これら 5 つのページング方法にはそれぞれ長所と短所があるため、特定のニーズやプロジェクトの実際の状況に応じて、適切なページング方法を選択できます。

以下は、MyBatis 物理ページング プラグインに基づくページングの実装です。

MyBatis物理ページングプラグインをインストールする

MyBatis 構成ファイルに次の構成を追加します。

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="dialect" value="mysql"/>
    </plugin>
</plugins>

PageHelper.startPage() メソッドを使用する

ページングを実装するには、Java コードで PageHelper.startPage() メソッドを使用します。

int pageNo = 1;
int pageSize = 10;
PageHelper.startPage(pageNo, pageSize);
List<User> userList = sqlSession.selectList("com.example.mapper.UserMapper.selectByPage");

ページングパラメータを構成する

PageHelper の静的メソッドを通じて設定できます。

PageHelper.offsetPage(offset, limit);
PageHelper.orderBy(orderBy);

このうち、offsetはオフセット、limitは各ページの番号、orderByはソート文を表します。

マッパーファイルでページネーションプラグインを使用する

ページング プラグインは、通常の SQL ステートメントと同じ方法で Mapper ファイルで使用されます。

<select id="selectByPage" resultMap="userResultMap">
    SELECT * FROM user
</select>

ページング クエリの結果からページング情報を取得する

ページング クエリの結果情報 (レコードの総数、現在のページ番号、ページごとのレコード数など) は、PageInfo クラスを通じて取得できます。

PageInfo<User> pageInfo = new PageInfo<>(userList);
long total = pageInfo.getTotal();
int currentPage = pageInfo.getPageNum();
int pageSize = pageInfo.getPageSize();

9. MyBatisの一括挿入方法は何ですか? バッチ挿入を実装するにはどうすればよいですか?

MyBatis でのバッチ挿入には、foreach タグ ループ挿入を使用する方法、BatchExecutor エグゼキュータを使用する方法、MyBatis-Spring バッチ操作を使用する方法、および MyBatis-Plus バッチ操作を使用する方法があります。
以下に、これら 4 つの方法で一括挿入を実装する方法を説明します。

1. foreach タグに基づくバッチ挿入:

优点:实现简单,适用于小批量数据插入;

缺点:对于大批量数据插入,会占用大量内存。

2. BatchExecutor に基づくバッチ挿入:

优点:适用于大批量数据插入,占用内存较少;

缺点:实现复杂,需要编写相应的代码。

3. MyBatis-Plus に基づくバッチ挿入方法:

优点:MyBatis-Plus提供了丰富的批量插入方法,使用方便;

缺点:需要引入MyBatis-Plus依赖,不太适合只使用MyBatis的项目。

4.カスタム プラグインに基づくバッチ挿入方法:

优点:灵活性高,可以根据需求定制批量插入规则;

缺点:需要编写插件代码,实现相对复杂。

一般に、これら 4 つのバッチ挿入方法にはそれぞれ長所と短所があり、特定のニーズと実際のプロジェクトの状況に応じて、適切なバッチ挿入方法を選択できます。

1. foreach タグを使用してループに挿入します

マッパー ファイルに SQL ステートメントを記述します。

<insert id="batchInsertUsers">
    INSERT INTO user(username, password, email)
    VALUES
    <foreach collection="users" item="user" separator=",">
        (#{user.username}, #{user.password}, #{user.email})
    </foreach>
</insert>

このうち、users は List 型のパラメータであり、user は List 内の要素型です。

Java コードで Mapper インターフェイスのメソッドを呼び出します。

List<User> userList = new ArrayList<>();
// 添加多个User对象到userList中
int result = userMapper.batchInsertUsers(userList);

Mapper インターフェースのメソッドを呼び出すときにパラメーターを設定します。

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("users", userList);
int result = userMapper.batchInsertUsers(paramMap);

このうち、usersはMapperファイルのforeachタグのcollection属性に相当し、userはforeachタグのitem属性に相当します。

ここでのパラメータのタイプは Map で、キーは foreach タグのコレクション属性の値、値は List タイプのパラメータであることに注意してください。

2. BatchExecutor エグゼキュータを使用する

MyBatis 構成ファイルに次の構成を追加します。

<settings>
    <setting name="defaultExecutorType" value="BATCH"/>
</settings>

Java コードで BatchExecutor エグゼキューターのインスタンスを作成し、Mapper インターフェイスのメソッドを呼び出します。

SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = new ArrayList<>();
// 添加多个User对象到userList中
for (User user : userList) {
    
    
    userMapper.insertUser(user);
}
sqlSession.flushStatements();
sqlSession.commit();
sqlSession.close();

このうち、ExecutorType.BATCH は BatchExecutor エグゼキュータを使用することを意味し、false はトランザクションを自動的にコミットしないことを意味します。

3. MyBatis-Spring バッチ操作を使用する

MyBatis-Spring では、SqlSession の操作をカプセル化する SqlSessionTemplate クラスが提供されており、このクラスを通じてバッチ挿入を実装できます。

Spring 構成ファイルに次の構成を追加します。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 其他配置 -->
    <property name="sqlSessionTemplate" ref="batchSqlSessionTemplate"/>
</bean>
<bean id="batchSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory"/>
    <constructor-arg index="1" value="BATCH"/>
</bean>

Java コードで SqlSessionTemplate のbatchUpdate() メソッドを呼び出して、バッチ挿入を実装します。

List<User> userList = new ArrayList<>();
// 添加多个User对象到userList中
int[] result = sqlSessionTemplate.batchUpdate("com.example.mapper.UserMapper.insertUser", userList);

このうち、第 1 パラメータは Mapper ファイル内の SQL ステートメントであり、第 2 パラメータはリスト型パラメータです。

4. MyBatis-Plusを使用したバッチ操作

MyBatis-Plus は、バッチ挿入などの便利なバッチ操作を提供する MyBatis の拡張ツールキットです。

Java コードで MyBatis-Plus のバッチ挿入メソッドを呼び出します。

List<User> userList = new ArrayList<>();
// 添加多个User对象到userList中
int result = userMapper.insertBatch(userList);

このうち、insertBatch()メソッドはMyBatis-Plusが提供する一括挿入メソッドであり、パラメータはList型のエンティティオブジェクトです。

10. MyBatis の楽観的ロックと悲観的ロックとは何ですか? 使い方?

MyBatis の楽観的ロックと悲観的ロックは、複数のスレッドがデータベースに同時にアクセスするときにデータの正確性を制御するために使用される 2 つのメカニズムです。

楽観的ロックと悲観的ロックの違いは、同時実行性を制御する方法です。

楽観的ロック

楽観的ロックとは、同時アクセス中にロックは実行されませんが、データのバージョン番号を制御することによってデータの正確性が保証されることを意味します。

具体的な実装方法は、テーブルにバージョン番号フィールドを追加し、データが更新されるたびにバージョン番号に 1 を加算します。

複数のスレッドが同時にデータを更新する場合、正常に更新できるのは 1 つのスレッドだけであり、他のスレッドはデータを再読み取りして更新する必要があります。

オプティミスティック ロックは、読み取りが多く書き込みが少ないシナリオに適しています。

MyBatis では、オプティミスティック ロックの実装は次の 2 つの手順に従う必要があります。

1) 以下に示すように、バージョン番号フィールドと @Version アノテーションをエンティティ クラスに追加します。

public class User {
    
    
    private Long id;
    private String name;
    private Integer age;
    @Version
    private Integer version;
    // getter/setter
}

2) Mapper で SQL ステートメントを記述するときは、バージョン番号を使用して更新を制御します。

次のように:

<update id="updateUser" parameterType="User">
    UPDATE user SET name=#{name}, age=#{age}, version=version+1
    WHERE id=#{id} AND version=#{version}
</update>

上記の SQL 文では、バージョンフィールドが自動的に 1 ずつインクリメントされますが、同時に WHERE 文でもバージョンが一致するかどうかがチェックされ、一致しない場合は更新は失敗します。

悲観的なロック

悲観的ロックとは、他のスレッドが同じデータにアクセスできないようにするために、同時アクセス中にロックすることを指します。

悲観的ロックは、SELECT ... FOR UPDATE ステートメントを通じて MyBatis に実装できます。

このステートメントはクエリ中にロックされ、他のスレッドがデータを変更できないようにします。

悲観的ロックは、書き込みが多く読み取りが少ないシナリオに適しています。

MyBatis で悲観的ロックを使用するには、次の 2 つの手順に従う必要があります。

1) Mapper で SQL ステートメントを記述する場合、SELECT...FOR UPDATE ステートメントを使用してロックし、

次のように:

<select id="getUserForUpdate" parameterType="Long" resultType="User">
    SELECT * FROM user WHERE id=#{id} FOR UPDATE
</select>

上記の SQL ステートメントでは、FOR UPDATE はクエリ中にロックされます。

2) Java コードで Mapper インターフェイスのメソッドを呼び出すときに、SqlSession の selectForUpdate() メソッドを使用してロックし、

次のように:

User user = sqlSession.selectOne("getUserForUpdate", 1L);
user.setName("newName");
int result = userMapper.updateUser(user);

上記の Java コードでは、selectOne() メソッドを使用してデータをクエリすると、他のスレッドがデータにアクセスできないようにロックが設定されます。その後、更新操作を実行します。

悲観的ロックは他のスレッドをブロックして待機させるため、システムの同時実行パフォーマンスが低下することに注意してください。そのため、特定のシナリオに従って実装を選択する必要があります。

11. MyBatis の一次キャッシュと二次キャッシュの違いは何ですか? 2次キャッシュを有効にするにはどうすればよいですか?

MyBatis の 1 次キャッシュと 2 次キャッシュはどちらもクエリ効率を向上させるために使用されるキャッシュ メカニズムですが、範囲とキャッシュ時間の点で異なります。

L1キャッシュ

第 1 レベルのキャッシュは SqlSession レベルのキャッシュを指し、その範囲は同じ SqlSession 内の複数のクエリ操作に限定されます。

同じ SQL ステートメントが同じ SqlSession で実行される場合、データはキャッシュから直接取得されるため、クエリ効率が向上します。1 次キャッシュはデフォルトで有効になっており、オフにすることはできません。

1次キャッシュをクリアする必要がある場合は、SqlSessionのclearCache()メソッドを実行するだけです。

L2キャッシュ

2 次キャッシュはマッパー レベルのキャッシュを指し、そのスコープは同じ名前空間内の複数の SqlSession です。

同じ SQL ステートメントが異なる SqlSession で実行される場合、データはキャッシュから取得されるため、クエリ効率が向上します。

2 次キャッシュはデフォルトでオフになっているため、手動でオンにする必要があります。

2 次キャッシュをオンにする場合は、構成ファイルで構成する必要があります。

次のように:

<configuration>
  <settings>
    <setting name="cacheEnabled" value="true"/>
  </settings>
  <typeAliases>
    <!-- type alias -->
  </typeAliases>
  <mappers>
    <!-- mapper -->
  </mappers>
  <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
</configuration>

上記の設定では、2次キャッシュを有効にするためにcacheEnabled属性が使用され、キャッシュの実装方法を指定するためにcacheタグが使用されます。

MyBatis は、Ehcache、Redis などのさまざまなキャッシュ実装メソッドを提供し、カスタム キャッシュ実装もサポートしています。

2 次キャッシュが有効な場合、クエリ結果のエンティティ クラスはシリアル化操作を実行するために Serializable インターフェイスを実装する必要があることに注意してください。

同時に、更新、挿入、削除などの操作では、キャッシュの正確性を確保するためにキャッシュを手動でクリアする必要があります。

12. MyBatis ではトランザクションはどのように実装されますか?

MyBatis のトランザクション実装では、JDBC ベースのトランザクション管理メカニズムが使用されます。

SqlSession の実行が完了し、トランザクションが送信されると、MyBatis は基礎となる JDBC 接続の commit() メソッドを呼び出してトランザクションを送信します。

実行中に例外が発生した場合、基礎となる JDBC 接続の rollback() メソッドが呼び出され、トランザクションがロールバックされます。

MyBatis のトランザクションは SqlSession によって管理されるため、MyBatis をトランザクション操作に使用する場合は、SqlSession オブジェクトを通じてトランザクションを管理する必要があります。

具体的な実装手順は次のとおりです。

1. SqlSessionFactory を通じて SqlSession オブジェクトを作成します。

2. SqlSession オブジェクトの getMapper() メソッドを使用して、操作する必要がある Mapper インターフェイスを取得します。

3. Mapper インターフェースでトランザクション操作を必要とするメソッドを定義し、そのメソッドに @Transaction アノテーションを付けます。

4. このメソッドで SqlSession の beginTransaction() メソッドを使用して、トランザクションを開始します。

5. トランザクション内でデータ操作を実行し、操作の完了後に SqlSession の commit() メソッドを呼び出してトランザクションを送信します。

6. 操作中に例外が発生した場合は、SqlSession の rollback() メソッドを呼び出してトランザクションをロールバックします。

以下は、トランザクション操作に MyBatis を使用するサンプル コードです。

public interface UserMapper {
    
    
    @Transactional
    void addUser(User user);
    @Transactional
    void updateUser(User user);
    @Transactional
    void deleteUser(int id);
}
public class UserServiceImpl implements UserService {
    
    
    private UserMapper userMapper;
    @Override
    @Transactional
    public void addUser(User user) {
    
    
        userMapper.addUser(user);
    }
    @Override
    @Transactional
    public void updateUser(User user) {
    
    
        userMapper.updateUser(user);
    }
    @Override
    @Transactional
    public void deleteUser(int id) {
    
    
        userMapper.deleteUser(id);
    }
}

上記のコードでは、UserMapper インターフェイスの addUser()、updateUser()、および deleteUser() メソッドが @Transactional アノテーションを使用したトランザクション管理に使用され、対応するメソッドが実装クラスで呼び出されます。

トランザクションを使用するときは、トランザクションの境界、つまりトランザクションのオープン、送信、ロールバックの操作に注意する必要があります。

13. MyBatis での遅延読み込みに対処するにはどうすればよいですか?

MyBatis の遅延ロードは、動的プロキシベースの遅延ロードと MyBatis ベースの遅延ロード メカニズムの 2 つの方法で実装できます。

動的プロキシベースの遅延読み込み

動的プロキシベースの遅延ロードは、MyBatis のデフォルトの遅延ロード方法です。

メイン オブジェクトをクエリする場合、MyBatis はメイン オブジェクトのみをクエリし、関連オブジェクトはクエリしません。

関連オブジェクトを使用する必要がある場合、MyBatis は動的プロキシを通じてプロキシ オブジェクトを生成し、プロキシ オブジェクトを通じて関連オブジェクトをロードします。

遅延読み込み機能を使用する必要がある場合は、Mapper.xml ファイル内で または タグを使用して、関連するオブジェクトを指定するだけです。

例えば:

<!-- 延迟加载一对一关系的关联对象 -->
<association property="author" column="author_id" select="getAuthorById" 
   fetchType="lazy"/>
    
<!-- 延迟加载一对多关系的关联对象 -->
<collection property="posts" column="id" select="getPostsByBlogId" 
   fetchType="lazy"/>

MyBatis 独自の遅延読み込みメカニズムに基づく

MyBatis に基づく遅延ロード メカニズムとは、MyBatis が提供する、特に遅延ロードの遅延ロードを担当するコンポーネントを使用することを指します。

このコンポーネントは、MyBatis 構成ファイルで構成する必要があります。

このコンポーネントを使用する場合、クエリ中に関連オブジェクトをロードできるように、クエリ ステートメントで ResultMap を使用して関連オブジェクトを指定する必要があります。

例えば:

<!-- 配置MyBatis自带的延迟加载机制 -->
<settings>
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 延迟加载一对一关系的关联对象 -->
<resultMap id="blogResult" type="Blog">
   <id property="id" column="id"/>
   <result property="title" column="title"/>
   <association property="author" column="author_id" 
      select="getAuthorById" fetchType="lazy"/>
</resultMap>
    
<!-- 延迟加载一对多关系的关联对象 -->
<resultMap id="blogResult" type="Blog">
   <id property="id" column="id"/>
   <result property="title" column="title"/>
   <collection property="posts" column="id" 
      select="getPostsByBlogId" fetchType="lazy"/>
</resultMap>

動的プロキシに基づく遅延ロード方法は、単一オブジェクトの遅延ロードのみをサポートすることに注意してください。つまり、1 対 1 の関係を持つ関連付けられたオブジェクトのみを遅延ロードできます。

MyBatis に基づく遅延ロード メカニズムは、1 対多の関係で関連付けられたオブジェクトの遅延ロードをサポートします。したがって、遅延読み込みを使用する場合は、特定のシナリオに基づいて選択する必要があります。

14. MyBatis の Mapper インターフェイスとは何ですか? それは何をするためのものか?

MyBatis では、Mapper インターフェイスは、SQL マッピング関係を定義するために使用されるインターフェイスを指します。

Mapper インタフェースは、注釈または XML ファイルを通じて SQL マッピング関係を定義します。定義された SQL ステートメントは、Mapper インタフェースのメソッドを呼び出すことで直接実行できます。

Mapper インターフェイスの機能には主に次の側面が含まれます。

1. SQL ステートメントを Java メソッドから分離して、コードの保守性と可読性を向上させます。

2. Mapper インターフェイスによって定義されたメソッドを通じて、SQL ステートメントを Java コードでより直感的な方法で実行できます。

3. Mapper インターフェースの動的プロキシ実装により、SQL ステートメントを手書きするという面倒なプロセスを省略し、開発効率を向上させることができます。

4. コードの再利用は、Mapper インターフェイスの継承とポリモーフィズムを通じて実現できます。

Mapper インターフェイスを実装するには 2 つの方法があります。1 つは XML ファイルに基づく Mapper マッパー、もう 1 つは注釈に基づく Mapper マッパーです。

XML ファイルに基づいた Mapper マッパーの実装では、SQL ステートメントをマップする XML ファイルを定義してから、Mapper インターフェイスで呼び出し用のメソッドを定義する必要があります。

注釈ベースの Mapper マッパー実装では、SQL ステートメントとメソッドは注釈を通じて定義され、呼び出されます。

つまり、Mapper インターフェイスは MyBatis の非常に重要なコンポーネントであり、Java コードと SQL ステートメントを分離し、コードの保守性と可読性を向上させ、開発効率も向上させます。

15. MyBatis で複数のデータ ソースを処理するにはどうすればよいですか?

MyBatis での複数のデータ ソースの処理は、次の 2 つの方法で実現できます。

複数の SqlSessionFactory の使用

Spring 構成ファイルで複数の SqlSessionFactory を定義することで、複数のデータ ソースを構成できます。各 SqlSessionFactory は 1 つのデータ ソースに対応します。

例えば:

<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/db1"/>
   <property name="username" value="root"/>
   <property name="password" value="root"/>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/db2"/>
   <property name="username" value="root"/>
   <property name="password" value="root"/>
</bean>
<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource1"/>
   <property name="mapperLocations" value="classpath*:mapper1/*.xml"/>
</bean>
<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource2"/>
   <property name="mapperLocations" value="classpath*:mapper2/*.xml"/>
</bean>

この方法では、データ ソースごとに SqlSessionFactory を構成し、各 SqlSessionFactory で対応するマッパー マッパーの場所を指定する必要があります。

MyBatis動的データソースの使用

MyBatisでは、動的なデータソースの切り替えを実現できるDynamicDataSourceというコンポーネントを提供しています。

DynamicDataSourceを使用する場合は、MyBatis設定ファイルで複数のデータソースを設定する必要があり、データソースを切り替える必要がある場合は、DynamicDataSourceのsetTargetDataSources()メソッドを呼び出して、切り替える対象のデータソースを設定します。

例えば:

<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/db1"/>
   <property name="username" value="root"/>
   <property name="password" value="root"/>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/db2"/>
   <property name="username" value="root"/>
   <property name="password" value="root"/>
</bean>
<bean id="dynamicDataSource" class="org.mybatis.dynamic.datasource.DynamicDataSource">
   <property name="targetDataSources">
      <map>
         <entry key="dataSource1" value-ref="dataSource1"/>
         <entry key="dataSource2" value-ref="dataSource2"/>
      </map>
   </property>
   <property name="defaultTargetDataSource" ref="dataSource1"/>
</bean>

DynamicDataSource を使用する場合は、Mapper インターフェイス メソッドに @DataSource アノテーションを追加して、使用するデータ ソースを指定する必要があることに注意してください。

例えば:

public interface UserDao {
    
    
   @DataSource("dataSource1")
   User getUserById(int id);
    
   @DataSource("dataSource2")
   List<User> getUsers();
}

上記は MyBatis で複数のデータ ソースを処理する 2 つの方法であり、特定のシナリオに応じて選択する必要があります。

16. MyBatis で挿入中に自動インクリメントされる主キーを取得するにはどうすればよいですか?

MyBatis への挿入時に自動インクリメントされる主キーを取得するには、次の 2 つの方法があります。

1. JDBC の getGeneratedKeys() メソッドを使用する

挿入操作を実行する前に、JDBC の getGeneratedKeys() メソッドを使用して自動インクリメント主キー値を取得し、マッパーの insert メソッドに useGeneratedKeys=true および keyProperty パラメーターを追加することでそれを指定されたプロパティに割り当てるように MyBatis に指示できます。インターフェース。

例えば:

@Insert("insert into user(name, age) values(#{name}, #{age})")
@Options(useGeneratedKeys=true, keyProperty="id")
int insertUser(User user);

この例では、 useGeneratedKeys=true は、JDBC の getGeneratedKeys() メソッドを使用して自動増加する主キー値を取得することを意味し、 keyProperty="id" は、自動増加する主キー値を User オブジェクトの id 属性に割り当てることを意味します。

2. selectKey タグを使用する

Mapper マッパーでは、selectKey タグを使用して、挿入中に自動インクリメントされる主キーを取得できます。

例えば:

<insert id="insertUser" parameterType="User">
   <selectKey resultType="int" keyProperty="id" order="AFTER">
      SELECT LAST_INSERT_ID()
   </selectKey>
   insert into user(name, age) values(#{name}, #{age})
</insert>

この例では、selectKey タグの resultType は返される自動インクリメント主キーのタイプを示し、keyProperty は自動インクリメント主キーの値が User オブジェクトの id 属性に割り当てられることを示し、order="AFTER" はそれを示します。 selectKey タグが挿入操作の後に実行されること、自動インクリメントされる主キー値を取得するための SQL ステートメント。

MyBatis で挿入時に自動インクリメントされる主キーを取得するには上記 2 つの方法がありますが、どちらを選択するかは状況に応じて決定してください。

17. MyBatis で遅延ロードとキャッシュを最適化するにはどうすればよいですか?

MyBatis での遅延ロードとキャッシュの最適化は、次の方法で実現できます。

1. 遅延読み込みを使用する

MyBatis では、lazyLoadingEnabled=true を設定することで遅延読み込みを有効にできます。

遅延ロード機能がオンになっている場合、MyBatis は遅延ロードされたプロパティを取得する必要がある場合にのみ追加の SQL クエリ ステートメントを発行するため、すべてのプロパティを一度にロードするオーバーヘッドが回避されます。

例えば:

<configuration>
   <settings>
      <setting name="lazyLoadingEnabled" value="true"/>
   </settings>
</configuration>

この例では、lazyLoadingEnabled 構成項目を使用して、遅延読み込み機能を有効にします。

2. 2次キャッシュを使用する

MyBatis では、二次キャッシュを使用してクエリ結果をキャッシュできます。Mapperマッパーにタグを追加し、MyBatis設定ファイルで2次キャッシュ機能を有効にする必要があります。

例えば:

<mapper namespace="com.example.UserMapper">
   <cache/>
   <select id="getUserById" resultType="User" useCache="true">
      select * from user where id=#{id}
   </select>
</mapper>

この例では、Mapper マッパーにタグを追加し、select タグで useCache="true" を使用して 2 次キャッシュ機能を有効にしました。

MyBatis 設定ファイルでは、2 次キャッシュ機能を有効にし、キャッシュ戦略を設定する必要があります。

例えば:

<configuration>
   <settings>
      <setting name="cacheEnabled" value="true"/>
   </settings>
   <typeAliases>
      <typeAlias type="com.example.User" alias="User"/>
   </typeAliases>
   <mappers>
      <mapper resource="com/example/UserMapper.xml"/>
   </mappers>
   <cache type="org.mybatis.caches.ehcache.EhcacheCache">
      <property name="timeToIdleSeconds" value="3600"/>
      <property name="timeToLiveSeconds" value="7200"/>
   </cache>
</configuration>

この例では、タグ内のタグを使用してキャッシュ戦略を構成し、キャッシュ タイプを EhcacheCache (キャッシュとして Ehcache を使用) として指定しました。

同時に、timeToIdleSeconds や timeToLiveSeconds などのキャッシュのプロパティを構成して、キャッシュの有効期限を制御することもできます。

上記は MyBatis での遅延ロードとキャッシュの最適化の方法であり、特定の状況に応じて選択する必要があります。

18. MyBatis の # と $ の違いは何ですか?

# と $ は、Java オブジェクトのプロパティ値を SQL ステートメントに置き換えるために使用されるプレースホルダー記号です。

# は、SQL インジェクション攻撃を効果的に防止できる安全なプレースホルダーで、受信パラメータ値をエスケープして SQL ステートメントに挿入します。

例えば:

SELECT * FROM user WHERE username = #{username}

この SQL ステートメントを実行すると、受信したユーザー名パラメーター値がエスケープされて SQL ステートメントに置き換えられ、SQL インジェクション攻撃を効果的に防ぐことができます。

$ は安全ではないプレースホルダーです。受信パラメータ値はエスケープされず、SQL ステートメントに直接配置されます。

例えば:

SELECT * FROM user WHERE username = '${username}'

この SQL ステートメントを実行すると、渡されたユーザー名パラメータ値が SQL ステートメントに直接置き換えられるため、SQL インジェクション攻撃に対して脆弱になります。

したがって、SQL ステートメントを結合するときは、SQL インジェクション攻撃を避けるために最初に # を使用する必要があります。

同時に、$ は、動的なテーブル名、並べ替えによる順序など、いくつかの特別なシナリオで使用できます。

19. Mybatis ではログはどのように処理されますか?

Mybatis では、ログの出力モードとレベルを設定によって制御できます。

Mybatis は、次のログ実装メソッドを提供します。

1. Log4j: log4j.jar ファイルをクラスパスに追加し、Mybatis 構成ファイルで構成する必要があります。

2. Log4j2: log4j2-core.jar および log4j2-api.jar ファイルをクラスパスに追加し、Mybatis 構成ファイルで構成する必要があります。

3. JDK ログ: Mybatis 設定ファイルで設定する必要があります。

4. SLF4J: slf4j-api.jar および対応する実装ライブラリ (slf4j-log4j12.jar など) をクラスパスに追加し、Mybatis 構成ファイルで構成する必要があります。

Mybatis のログ レベルには、TRACE、DEBUG、INFO、WARN、ERROR が含まれます。

ログ レベルは、Mybatis 設定ファイルで設定することで設定できます。

たとえば、ログレベルを DEBUG に設定すると、SQL 文や実行時間などの詳細情報が出力され、デバッグや最適化が容易になります。

同時に、ログの出力方法を構成して、ログをコンソール、ファイル、またはデータベースに出力して、簡単に表示および分析できるようにすることができます。

実際のプロジェクトでは、ニーズや実態に応じて適切なログの実装方法やレベルを選択する必要があります。

20. Mybatis の動的プロキシとは何ですか? 使い方?

Mybatis は、動的プロキシ テクノロジを使用して、DAO インターフェイスの実装クラスを実装します。

ダイナミック プロキシは、実行時にプロキシ クラスを生成するテクノロジであり、DAO 実装クラスを手動で記述する手順を省略できます。

Mybatis では、DAO インターフェイスを作成し、Mybatis 構成ファイルで対応する DAO 実装クラスを構成するだけで済みます。

具体的な利用手順は以下の通りです。

1. DAO インターフェイスを作成し、実装する必要があるメソッドを定義します。

2. Mybatis 構成ファイルで、ラベルを使用して DAO インターフェースのマッピング関係を構成し、DAO インターフェースの完全修飾名と対応する SQL ステートメントを指定します。

3. SqlSession の getMapper() メソッドで DAO インターフェースの実装クラスオブジェクトを取得します。

4. DAO インターフェイス メソッドを呼び出してデータベースを操作します。

動的プロキシの実装原理は次のとおりです。

Java のリフレクション メカニズムを通じて、プロキシ クラスが実行時に動的に生成され、メソッド呼び出しが SqlSession の対応するメソッドに転送されて処理されます。

これにより、DAO 実装クラスを手動で記述する必要がなくなり、データ アクセスとビジネス ロジックも分離されるため、コードの保守性と拡張性が向上します。

動的プロキシを使用する場合は、DAO インターフェイスのメソッド名が対応する SQL ステートメントの ID と一致していることを確認する必要があることに注意してください。一致しないと、実行時エラーが発生します。

同時に、実際の状況を総合的に考慮して、DAO インターフェースを実装する適切な方法を選択することも必要です。

21. Mybatisにおけるアノテーション方式とXML方式の違いは何ですか? どのように選ぶか?

Mybatis は、マッピング関係を構成する 2 つの方法、アノテーション モードと XML モードを提供します。

どちらの方法にもそれぞれ長所と短所があり、実際の状況に応じて適切な方法を選択する必要があります。

アノテーションの利点:

1. 簡潔かつ明確で、多数の XML 構成ファイルを記述する必要はありません。

2. 便利かつ高速で、追加の構成を必要とせずに Java クラスで直接アノテーションを作成できます。

3. 保守が容易で、すべての構成は Java クラス内にあるため、集中管理と変更に便利です。

アノテーション方式の欠点:

1. 可読性が低く、複雑なマッピング関係で混乱を招きやすい。

2. 動的SQL構成は実行できません。

XML 方式の利点:

1. 可読性が高く、すべての SQL ステートメントとマッピング関係を明確に表示できます。

2. 動的SQLは設定が簡単で、条件判定やループ処理などが可能です。

3. 保守が容易で、XML ファイルを直接変更して構成できます。

XML 方式の欠点:

1. 多数の XML 構成ファイルを記述する必要があるため、エラーが発生しやすくなります。

2. 構成は煩雑で、多数のラベルと属性の構成が必要であり、構成エラーが発生しやすいです。

アノテーション方式とXML方式のどちらを選択するかについては、実情に応じて総合的に検討する必要があります。

一般に、マッピング関係が比較的単純で SQL ステートメントが比較的固定されている場合は、アノテーション方法を選択できます。

マッピング関係が複雑で、SQL ステートメントを動的に構成する必要がある場合は、XML メソッドを選択できます。

同時に、アノテーション方式とXML方式を組み合わせて、それぞれの利点を最大限に発揮することもできます。

22. Mybatis の resultMap とは何ですか? 使い方?

Mybatis では、ResultMap はデータベース内のレコードを Java オブジェクトにマップする方法を記述する方法です。

ResultMap を使用すると、データベース クエリ結果の列を Java オブジェクトのプロパティにマップできるため、クエリ結果を Java オブジェクトに簡単にカプセル化できます。

具体的な使い方は以下の通りです。

1. Mybatis マッピング ファイルで、ラベルを使用して ResultMap を定義します。

<resultMap id="userMap" type="com.example.User">
  <result property="id" column="user_id" />
  <result property="username" column="user_name" />
  <result property="password" column="user_password" />
</resultMap>

このうち、id 属性は ResultMap の一意の識別子を指定し、type 属性はマップされた Java の型を指定し、タグ内の property 属性は Java オブジェクトの属性名を指定し、column 属性はデータベース内の列名を指定します。

2. SQL ステートメントで ResultMap を使用する

<select id="getUser" resultMap="userMap">
  SELECT user_id, user_name, user_password FROM user WHERE user_id = #{id}
</select>

クエリ ステートメントでは、resultMap 属性を通じて以前に定義した ResultMap を参照します。

3. Java コードでクエリ結果にアクセスする

SqlSession session = sqlSessionFactory.openSession();
try {
    
    
  User user = session.selectOne("getUser", 1);
  ...
} finally {
    
    
  session.close();
}

Java コードでは、クエリ ステートメントは SqlSession の selectOne() メソッドを通じて実行され、クエリ結果は指定された型の Java オブジェクトにカプセル化されます。

ResultMap を使用すると、データベース クエリの結果を Java オブジェクトにカプセル化して、コードの可読性と保守性を向上させることができます。

同時に、ResultMap は継承や関連付けなどの高度な機能もサポートしており、実際の状況に応じて柔軟に構成できます。

23. Mybatis で接続プールを構成するにはどうすればよいですか?

Mybatis では、接続プールの構成は Mybatis 構成ファイルを構成することによって実現されます。

Mybatis に付属の接続プールを使用することも、Druid、C3P0 などのサードパーティの接続プールを使用することもできます。

具体的な設定方法は以下の通りです。

1. Mybatis に付属の接続プールを使用する

Mybatis 構成ファイルでは、データ ソースはタグを通じて構成され、最大接続数、最小接続数、接続タイムアウトなど、接続プールのいくつかのパラメーターを設定できます。

構成例は次のとおりです。

<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <property name="poolMaximumActiveConnections" value="20" />
        <property name="poolMaximumIdleConnections" value="10" />
        <property name="poolPingEnabled" value="true" />
        <property name="poolPingQuery" value="SELECT 1" />
        <property name="poolPingConnectionsNotUsedFor" value="3600" />
      </dataSource>
    </environment>
  </environments>
</configuration>

この構成では、タグの type 属性で使用する接続プールのタイプを指定します。ここでは POOLED が使用されており、Mybatis に付属の接続プールが使用されることを示します。

次のタグでは、接続プールの一部のパラメーター (ドライバー、URL、ユーザー名、パスワードなど) と、接続プールの一部のプロパティ (poolMinimumActiveConnections、poolMinimumIdleConnections など) が構成されます。

2. サードパーティの接続プールを使用する

サードパーティの接続プールを使用するには、まず対応する jar パッケージをインポートし、それに応じて Mybatis 構成ファイルで構成する必要があります。ドルイド僧を例にとると、

構成例は次のとおりです。

<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC" />
      <dataSource type="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="root" />
        <property name="initialSize" value="5" />
        <property name="maxActive" value="20" />
        <property name="minIdle" value="5" />
        <property name="maxWait" value="60000" />
        <property name="timeBetweenEvictionRunsMillis" value="60000" />
        <property name="minEvictableIdleTimeMillis" value="300000" />
        <property name="poolPreparedStatements" value="true" />
        <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
        <property name="filters" value="stat,wall" />
      </dataSource>
    </environment>
  </environments>
</configuration>

この構成では、タグの type 属性は使用される接続プールのタイプを指定します。ここでは DruidDataSource が使用されます。

次のタグでは、driverClassName、url、ユーザー名、パスワードなどの接続プールのいくつかのパラメータと、initialSize、maxActive などの接続プールのいくつかの属性が構成されます。

Druid 接続プールは、監視、ファイアウォールなどの追加機能も提供しており、フィルター属性を設定することで有効にすることができることに注意してください。

24. Mybatis の TypeHandler とは何ですか? 使い方?

Mybatis では、TypeHandler は Java 型と JDBC 型の間の変換を処理するために使用されるメカニズムです。

通常の状況では、Mybatis は Java 型と JDBC 型を自動的に変換できますが、Java 型がデータベース内のフィールド型と一致しない場合や、特殊な変換操作が必要な場合など、特殊な場合には TypeHandler を使用する必要があります。 . カスタム型変換を実行します。

具体的な使い方は以下の通りです。

1. TypeHandlerインターフェースを実装する

まず、型変換を処理するためのいくつかのメソッドが含まれる TypeHandler インターフェイスを実装する必要があります。

一般的に使用される実装クラスは 2 つあります。1 つは BaseTypeHandler クラスを継承するもので、もう 1 つは TypeHandler インターフェイスを実装するものです。

以下は、TypeHandler インターフェイスを実装するサンプル コードです。

public class MyTypeHandler implements TypeHandler<String> {
    
    
  @Override
  public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    
    
    ps.setString(i, parameter);
  }
  @Override
  public String getResult(ResultSet rs, String columnName) throws SQLException {
    
    
    return rs.getString(columnName);
  }
  @Override
  public String getResult(ResultSet rs, int columnIndex) throws SQLException {
    
    
    return rs.getString(columnIndex);
  }
  @Override
  public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
    
    
    return cs.getString(columnIndex);
  }
}

このサンプル コードでは、MyTypeHandler は TypeHandler インターフェイスを実装します。ここで、ジェネリックは処理する必要がある Java 型を表します。

インターフェイス内の 4 つのメソッドはさまざまな型変換操作に対応しており、必要に応じて特定の実装が記述されます。

2. Mybatis 設定ファイルで設定する

Mybatis 設定ファイルでは、タグを通じて TypeHandler を設定できます。

サンプルコードは次のとおりです。

<configuration>
  <typeHandlers>
    <typeHandler handler="com.example.MyTypeHandler" />
  </typeHandlers>
</configuration>

この構成では、タグ内にTypeHandlerを設定し、handler属性でTypeHandlerの実装クラスを指定する。

異なる Java 型で型変換を実行する必要がある場合、これを実現するために複数の TypeHandler を構成できることに注意してください。

3. マッピング ファイルで TypeHandler を使用する

マッピング ファイルでは、typeHandler 属性を通じて、Java 型と JDBC 型の間の変換を処理するためにどの TypeHandler を使用するかを指定できます。

サンプルコードは次のとおりです。

<resultMap id="userMap" type="com.example.User">
  <result property="id" column="user_id" />
  <result property="username" column="user_name" typeHandler="com.example.MyTypeHandler" />
  <result property="password" column="user_password" />
</resultMap>

このサンプルコードでは、タグの typeHandler 属性で、対応する属性で使用する TypeHandler を指定していますが、ここでは事前に設定した MyTypeHandler を使用します。

TypeHandler を使用すると、Java 型と JDBC 型の間の変換をカスタマイズして、コードの柔軟性と保守性を向上させることができます。

25. Mybatis でファジー クエリを実行するにはどうすればよいですか?

Mybatis では、ファジー クエリにワイルドカードを使用できます。ワイルドカードには次の 2 種類があります。

パーセント記号 (%!) (欠落): 任意の数の文字を表し、ファジー クエリの先頭、末尾、または途中に出現できます。

アンダースコア (_): 任意の 1 文字を表し、ファジー クエリの途中にのみ使用できます。
例:
フィールド名を持つテーブル ユーザーがいて、ファジー クエリを実行する必要があるとします。次の SQL ステートメントを使用できます。

SELECT * FROM user WHERE name LIKE '%!张(MISSING)%!'(MISSING)

この SQL ステートメントは、名前フィールドに Zhang を含むすべてのレコードをクエリできます。

Mybatis では、KaTeX 解析エラー: Expected 'EOF', got '#' at Position 4: {} または #̲{} を使用してパラメータを挿入できます。次の場合は... {} ワイルドカードを挿入します

例は次のとおりです。

<select id="getUserByName" resultType="User">
    SELECT * FROM user WHERE name LIKE '%!$(MISSING){name}%!'(MISSING)
</select>

この SQL クエリ ステートメントの ${name} は、ファジー クエリを実装できる %! (MISSING) ワイルドカード文字を含む SQL ステートメントのパラメーター内の名前を挿入することを意味します。

パラメータの挿入に ${} を使用すると、SQL インジェクションのリスクが伴うことに注意してください。パラメータが信頼できない場合は、パラメータの挿入に #{} を使用する必要があります。

例は次のとおりです。

<select id="getUserByName" resultType="User">
    SELECT * FROM user WHERE name LIKE CONCAT('%!'(MISSING), #{name}, '%!'(MISSING))
</select>

この SQL クエリ ステートメントは、CONCAT 関数を使用して %!(MISSING) と #{name} を完全な文字列に連結します。これにより、SQL インジェクションの問題を回避できます。

26. Mybatis で複数テーブルのクエリを実行するにはどうすればよいですか? 1 対多および多対多の関係にどのように対処するか?

次のメソッドを使用して、Mybatis で複数テーブルのクエリを実行できます。

1. ネストされたクエリを使用する:mapper.xml ファイル内で複数の select ステートメントを使用してネストされたクエリを実行し、クエリ ステートメント内でネストされたクエリを使用して関連データを取得します。

2. 結合クエリを使用する:mapper.xml ファイル内の複数のテーブルの結合クエリ ステートメントを使用し、結合によって複数のテーブルを接続し、関連データを取得します。

3. Mybatis-Plus が提供する相関クエリを使用します。Mybatis-Plus は、1 対多、多対多などのさまざまな相関クエリ方法を提供します。相関関係を定義することで関連データを取得できます。

1 対多および多対多の関係を扱う場合は、次のメソッドを使用できます。

1. 1 対多の関係: エンティティ クラスで List タイプの属性を定義し、複数のエンティティ オブジェクトを List に配置します。これは、1 つのエンティティ オブジェクトが複数の関連オブジェクトに対応することを示します。

2. 多対多の関係: エンティティ クラスで Set タイプ属性を定義し、複数のエンティティ オブジェクトを Set に配置します。これは、1 つのエンティティ オブジェクトと複数の関連オブジェクトの間に多対多の関係があることを示します。同時に、2 つのテーブル間の関係を維持するために中間テーブルを作成する必要があります。

上記は、Mybatis での複数テーブルのクエリと 1 対多および多対多のリレーションシップの処理の基本的なメソッドです。特定の実装は、特定の状況に応じて調整する必要があります。

27. Mybatis でマルチテーブル クエリを構成するにはどうすればよいですか? N+1問題とは何ですか? N+1 クエリを回避するにはどうすればよいですか?

次のメソッドを使用して、Mybatis で複数テーブルのクエリを実行できます。

1. ネストされたクエリを使用する:mapper.xml ファイル内で複数の select ステートメントを使用してネストされたクエリを実行し、クエリ ステートメント内でネストされたクエリを使用して関連データを取得します。

2. 結合クエリを使用する:mapper.xml ファイル内の複数のテーブルの結合クエリ ステートメントを使用し、結合によって複数のテーブルを接続し、関連データを取得します。

3. Mybatis-Plus が提供する相関クエリを使用します。Mybatis-Plus は、1 対多、多対多などのさまざまな相関クエリ方法を提供します。相関関係を定義することで関連データを取得できます。

N+1問題とは何ですか?

Mybatis の N+1 問題とは、クエリの実行時に、クエリ結果に他の関連テーブルのデータが含まれている場合、メイン テーブルのデータをクエリした後、関連テーブルに対して N 回の個別のクエリを実行する必要があることを意味します。合計 N+1 個のクエリが発生します。

この状況では、大量のデータベース アクセスとネットワーク オーバーヘッドが発生するため、データベースのパフォーマンスの問題が発生する可能性があります。

たとえば、注文テーブルと製品テーブルがあると仮定すると、注文には複数の製品を含めることができます。

すべての注文と各注文の製品リストをクエリする必要がある場合、Mybatis のデフォルトの方法を使用すると、最初にすべての注文の基本情報をクエリし、次に各注文に対応する製品リストをクエリします。これには N+1 が必要です。 N は注文数です。

この状況を回避するには、Mybatis が提供する遅延読み込み機能を使用するか、ネストされたクエリなどの最適化手法を使用して N+1 問題を解決します。

N+1 クエリを回避するために、Mybatis が提供する遅延ロード メカニズムとバッチ ロード メカニズムを使用できます。

遅延ロード: Mybatis は、クエリ中に関連オブジェクトをロードせず、実際に使用されるときにのみロードする遅延ロード メカニズムを提供します。遅延読み込みは、mapper.xml ファイルで fetchType="lazy" を設定することで実現できます。

バッチ ロード: Mybatis は、データベースへの複数のクエリを回避するために、クエリ中に複数のオブジェクトを一度にロードできるバッチ ロード メカニズムを提供します。バッチ読み込みは、mapper.xml ファイルで fetchType="lazy" および batch="true" を設定することで実現できます。

上記は、Mybatis で複数テーブル クエリを実行し、N+1 クエリを回避するための基本的な方法です。特定の実装は、特定の状況に応じて調整する必要があります。

28. MyBatis と Hibernate の類似点と相違点、およびそれぞれの長所と短所

MyBatis と Hibernate はどちらも優れた Java 永続化フレームワークであり、それらの類似点と相違点、およびそれぞれの長所と短所は次のとおりです。

同じ点:

1. これらはすべて Java 永続フレームワークであり、ORM (オブジェクト リレーショナル マッピング) およびデータ アクセス操作の実装に使用されます。

2. すべては、追加、削除、変更、クエリなどの操作を含む、一般的なデータベース操作をサポートします。

3. すべてがトランザクション処理メカニズムをサポートし、複数の操作でトランザクション管理を実行できます。

違い:

1. 異なるフレームの位置:

MyBatis は SQL の記述と最適化にさらに注意を払い、柔軟な SQL ステートメントの記述とカスタマイズされた SQL マッピングをサポートし、よりきめ細かい方法で SQL ステートメントの実行を制御できます。

Hibernate は、オブジェクトのマッピングと関係の維持にさらに注意を払い、オブジェクト指向の操作とクエリをサポートします。

2. さまざまなマッピング方法:

MyBatis はマッピングに XML または注釈を使用するため、SQL をきめ細かく制御できます。

Hibernate は、エンティティ マッピングに JPA アノテーションまたは XML 設定ファイルを使用します。

3. 異なるパフォーマンス:

MyBatis は SQL ステートメントを直接操作でき、オブジェクト リレーショナル マッピングを必要としないため、通常、Hibernate よりもパフォーマンスが高くなります。

Hibernate は、オブジェクト リレーショナル マッピングのため、パフォーマンスの点で比較的遅くなります。

4. さまざまな構成方法:

MyBatis の構成は比較的単純で、必要なのはデータ ソースと SQL マッピング ファイルを構成することだけです。

Hibernate の構成は比較的複雑で、データ ソースの構成、エンティティ マッピング、関係マッピング、およびその他の構成が必要です。

5. 異なる使用体験:

MyBatis はより柔軟で、複雑な SQL ステートメントやカスタム SQL マッピングを作成できますが、多数の SQL ステートメントを手動で作成する必要があります。

Hibernate はより便利で、オブジェクト指向の方法で操作およびクエリを実行できますが、複雑な SQL ステートメントのサポートが不十分です。

MyBatis の利点:

1. 高い柔軟性、SQL ステートメントとマッピングをカスタマイズできます。

2. パフォーマンスが良く、SQL 文を直接操作できます。

3. 使いこなしやすく、設定も簡単です。

MyBatis の欠点:

1. オブジェクトのマッピングは面倒で、SQL ステートメントを手動で記述する必要があります。

2. オブジェクト指向のクエリ方式はサポートされていません。

休止状態の利点:

1. オブジェクト指向で使いやすい。

2. オブジェクト指向のクエリ方法をサポートします。

3. オブジェクトのマッピングが便利で、SQL ステートメントを自動生成できます。

休止状態の欠点:

1. パフォーマンスが低く、オブジェクト リレーショナル マッピングが必要です。

2. 構成は比較的複雑です。

3. カスタム SQL ステートメントの最適化はサポートされていません。

要約すると、MyBatis と Hibernate はどちらも優れた永続化フレームワークであり、実際のビジネス ニーズとテクノロジの選択に基づいてどちらのフレームワークを使用するかを選択する必要があります。

29. MyBatis の resultType と javaType の違いは何ですか?

MyBatis の resultType と javaType は両方とも、クエリ結果セット内の列のデータ型を指定するために使用されますが、それらの使用シナリオと意味は少し異なります。

結果の種類

resultType は、マッピング結果セットのタイプを指定するために使用されます。これは、Java 基本タイプ、JavaBean、Map など、またはカスタム タイプにすることができます。

resultType を使用する場合、MyBatis は自動マッピングを通じてクエリ結果セット内の列名と JavaBean 内のプロパティ名を照合し、結果セットと Java オブジェクト間のマッピングを実現します。

使用例:

<select id="getUserById" resultType="com.example.User">
  select id, name, age from user where id = #{id}
</select>

javaタイプ

javaType は、クエリ パラメータのタイプを指定するために使用されます。これは、受信パラメータ値をどの Java タイプに変換するかを MyBatis に伝えるために使用されます。

クエリパラメータをマッピングするとき、MyBatis は javaType で指定された型に従って変換し、変換された値を SQL ステートメントのプレースホルダに渡します。

使用例:

<select id="getUserByName" resultType="com.example.User">
  select id, name, age from user where name = #{name, javaType=String}
</select>

一般に、resultType と javaType の両方は型のマッピングに使用されますが、resultType は結果セット型のマッピングに使用され、javaType はクエリ パラメータ型のマッピングに使用されます。使用する場合は、さまざまなシナリオやニーズに応じて選択する必要があります。

30. MyBatisのネストクエリとは何ですか?

MyBatis のネストされたクエリは、関連テーブルをクエリする方法であり、ネストされた select ステートメントを使用して関連クエリを実装します。

具体的には、ネストされたクエリには 1 つの SQL ステートメント内に別の SQL ステートメントが含まれており、サブクエリの結果をクエリした後、その結果が外側のクエリの条件として使用されます。

ネストされたクエリには、特定の部門のすべての従業員情報のクエリ、特定のユーザーのすべての注文情報のクエリなど、幅広い使用シナリオがあります。

MyBatis では、ネストされたクエリは次の方法で実装できます。

1. ネストされたクエリを実行するには、関連付けタグを使用します。関連付けタグを使用すると、2 つのテーブル間の関係を Java オブジェクトの関連付けにマップし、ネストされた SELECT ステートメントを通じて関連付けられたテーブルのデータをクエリできます。

サンプルコード:

<select id="getDepartmentById" resultMap="departmentMap">
  select * from department where id = #{id}
</select>
<resultMap id="departmentMap" type="Department">
  <id property="id" column="id" />
  <result property="name" column="name" />
  <association property="employees" javaType="List" resultMap="employeeMap">
    <select id="getEmployeesByDepartmentId" resultMap="employeeMap">
      select * from employee where department_id = #{id}
    </select>
  </association>
</resultMap>
<resultMap id="employeeMap" type="Employee">
  <id property="id" column="id" />
  <result property="name" column="name" />
  <result property="age" column="age" />
  <result property="departmentId" column="department_id" />
</resultMap>

2. コレクション タグを使用してネストされたクエリを実行します。コレクション タグを使用すると、2 つのテーブル間の関係を Java オブジェクトのコレクション関係にマップし、ネストされた SELECT ステートメントを通じて関連テーブルのデータをクエリできます。

サンプルコード:

<select id="getUserOrders" resultMap="userMap">
  select * from user where id = #{id}
</select>
<resultMap id="userMap" type="User">
  <id property="id" column="id" />
  <result property="name" column="name" />
  <result property="age" column="age" />
  <collection property="orders" resultMap="orderMap">
    <select id="getOrdersByUserId" resultMap="orderMap">
      select * from order where user_id = #{id}
    </select>
  </collection>
</resultMap>
<resultMap id="orderMap" type="Order">
  <id property="id" column="id" />
  <result property="name" column="name" />
  <result property="price" column="price" />
  <result property="userId" column="user_id" />
</resultMap>

一般に、MyBatis のネストされたクエリは、複数テーブル関連のクエリの機能を簡単に実装し、クエリの効率と精度を向上させることができますが、クエリ ステートメントの複雑さとパフォーマンスの問題に注意する必要があります。

おすすめ

転載: blog.csdn.net/qq_43012298/article/details/129465431