MyBatis Persistence Layer Framework の詳細な解釈: 構成ファイルの追加、削除、変更、および確認の実践トレーニング

1 はじめに

以前、MyBatis 永続層フレームワークのネイティブ開発方法と Mapper エージェント開発方法を学び、JDBC 基本コードを使用してデータベースを操作する際のハードコーディングと煩雑な操作の問題を解決しました。記事によってもたらされたフィードバックは悪くないので、今日は以前に学んだ内容を使用して、実践的なケース トレーニングを行いましょう。

振り返ってみると、なぜ MyBatis を使用して開発を行っているのでしょうか。MyBatis が優れた永続化レイヤー フレームワークとして、カスタム SQL、ストアド プロシージャ、および高度なマッピングをサポートしていることを理解するのは難しいことではありません.すべての JBDC コードと、パラメーターを設定して結果セットを取得する作業がほとんどなくなります。図に示すように、JBDC 基本コードを使用してデータベースを操作する際の Java コードのハードコーディングと面倒な操作の問題を解決します。

このセクションのケースのトレーニング目標: 構成ファイルを使用して、追加、削除、変更、およびチェックの操作を実現できるようになります。

2.準備

現在、MyBatis を使用して、データベース内のデータの追加、削除、変更、およびクエリを完了しています。具体的な実装は次のとおりです。

  • クエリデータ
    • すべてのデータを照会する
    • クエリ データの詳細
    • 条件付きクエリ
  • データの追加
  • データを変更する
    • すべてのフィールドを変更する
    • 動的フィールドを変更する
  • データを削除する
    • 個人データの削除
    • 一括データ削除

今日のケースでは、データベース内のデータを追加、削除、変更、およびクエリするために、MyBatis を介して、学生 ID、名前、性別、成績、およびその他のフィールド情報を含む学生データ テーブルが与えられます。記事が長いため、このシリーズの記事は 2 つの記事に分けられます. 最初の記事ではクエリ操作について説明し、後の記事では追加、削除、および変更について説明します. この部分の内容に興味がある場合は、次の記事に移動します。

まず、データベース テーブルを作成し、データを追加する必要があります. 関連する SQL ステートメントは次のとおりです。

drop table if exists student;

create table student(
	id int primary key auto_increment,
	name varchar(10),
	gender char(1),
	score_english int,
	score_math int
);

insert into student(name,gender,score_english,score_math) values
('张三','男',61,65),
('李四','女',45,38),
('王五','男',85,53),
('小王','男',56,58),
('小樊','女',85,92);

データテーブルは次のとおりです。

画像-20230129193400530

次に、 idea のorg.chengzi.pojoパッケージ。

public class Student{
    
    
    //id 主键
    private int id;
    //学生姓名
    private String name;
    //学生性别
    private String gender;
    //学生英语成绩
    private int scoreEnglish;
    //学生数学成绩
    private int scoreMath;
    
    //这里省略了Getter and Setter方法和重写的Object中的toString方法
}

次に、テスト ケースを記述し、ここで Test に単体テスト コードを記述し、テスト コードの Java ファイル ディレクトリに MyBatisTest クラスを作成します。写真に示すように:

画像-20230129194459753

MyBatis の開発効率を向上させるために、 MyBatisXプラグインをインストールします.このプラグインには、XML マッピング構成ファイルと Mapper インターフェイス間の相互ジャンプと、自動的に図に示すように、Mapper インターフェイス メソッドに従ってステートメントを生成します。

画像-20230129194834069

File/setting/plugins で MyBatisX プラグインを検索し、ダウンロードしてインストールします。

青い画像は Mapper インターフェイス ファイルを表し、赤いアイコンは SQL マッピング構成ファイルを表します. このプラグインを使用すると、Mapper インターフェイスでメソッドを定義し、構成ファイルでステートメントを自動的に生成し、対応する Mapper にすばやくジャンプできます。構成ファイルのインターフェイス。このプラグインは MyBatis の開発にとても有効だと思い、MyBatis を学んでからずっと使っています。

3.すべてのデータをクエリする

クライアント ページでは、通常、すべてのデータ情報を表示する必要がありますが、このとき、基盤となるコードは Java を使用してデータベースを操作し、すべての情報をクエリしてクライアント ページに送信することです。

次の手順ですべての情報を照会できます。

  • Mapper インターフェースを書く
    • パラメータ: なし
    • 結果:List<Student>
  • SQL マッピング構成ファイルの書き込み
  • テストコードを書いて実行する

Mapper インターフェースのメソッドを分析する場合、主に操作データの要件に応じてパラメーターと戻り値の型が必要かどうかを分析します。

3.1 インターフェイスメソッドの記述

org.chengzi.mapperパッケージに StudentMapper インターフェースを作成し、このインターフェースですべての学生データを照会するメソッドを定義します。

public interface StudentMapper {
    
    
    /*
    需求:查询所有学生信息
     */
    List<Student> selectAll();

}

3.2 SQL文を書く

リソース パスの下にディレクトリ構造を作成します。Mapper インターフェイスと対応する SQL マッピング構成ファイルが同じファイル ディレクトリにあることを確認するにはorg/chengzi/mapper、パス区切り記号を使用する必要があります。/このディレクトリに StudentMapper.xml 構成ファイルを作成します。

対応するメソッドを StudentMapper インターフェイスに記述した後、MyBatisX プラグインのアイコンを使用して、対応する sql マッピング構成ファイルにすばやくジャンプでき、ステートメントが自動的に生成されます。sql ステートメントを記述して、sql マッピング構成ファイル内のすべての学生情報を照会します。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.chengzi.mapper.StudentMapper">
    <select id="selectAll" resultType="student">
        select *
        from student;
    </select>
</mapper>

3.3 テストメソッドを書く

MyBatisTest クラスで、次のように、すべての学生情報をテストおよびクエリするためのコードを記述します。

public class MyBatisTest {
    
    
    @Test
    public void testSelectAll() throws IOException {
    
    
        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        //4. 执行方法
        List<Student> students = studentMapper.selectAll();
        System.out.println(students);

        //5. 释放资源
        sqlSession.close();
    }
}

将来 SSM フレームワークを学習した後、コードのこの部分は非常に単純になります. ここでの焦点は、メソッドを実行するコードの 1 行です.

操作結果:

画像-20230129202650613

ここで、データベース内の一部のフィールドの情報が Java オブジェクトにカプセル化されていないことが判明しました.この問題の理由は非常に単純です.データベース内のテーブルの列名がエンティティ クラスの属性名と一致していないからです.たとえば、生徒の数学の点数、MySQL では Java では score_math という名前のメソッドが使用されていますが、Java では scoreMath という名前で、2 つの命名方法で問題ありません。

この問題を解決するには、次の 2 つの方法があります

  1. データ テーブルのフィールド名のエイリアス
  2. resultMap を使用して、フィールド名と属性名の間のマッピング関係を定義します

例えば:

<mapper namespace="org.chengzi.mapper.StudentMapper">
    <select id="selectAll" resultType="student">
        select id,name,gender,score_english as scoreEnglish,score_Math as scoreMath
        from student;
    </select>
</mapper>

この時点で、データをオブジェクトにカプセル化できないという問題は解決されましたが、すべての学生情報を照会する場合、すべてのフィールド名をリストする必要があり、これは明らかに非効率的であり、お勧めできません。MyBatis は、この問題を解決するための sql フラグメントを提供します。

例えば:

<mapper namespace="org.chengzi.mapper.StudentMapper">
    <!--
	sql片段
	-->
    <sql id="student_column">
        select id,name,gender,score_english as scoreEnglish,score_Math as scoreMath
    </sql>
    
    <select id="selectAll" resultType="student">
        <include refid="student_column"/>
        from student;
    </select>
</mapper>

id は sql フラグメントの一意の識別子として使用され、使用<include>時には元の sql ステートメントでラベル参照を使用するだけで十分です。

これは別の問題です. データ テーブルのいくつかのフィールドを操作すると、多数の sql フラグメントが生成されます. これは明らかにお勧めできません. すべての MyBatis は、resultMap メソッドを使用してこの問題を解決します.

3.4 resultMap の使用

データ テーブルの一部のフィールドを Java オブジェクトにカプセル化できないという問題を解決する場合、エイリアスを使用する方法は効率が悪く、sql フラグメントの方法は柔軟ではありません. MyBatis は、フィールド名とフィールド間のマッピング関係を定義する resultMap メソッドを提供します.属性名。

使用する場合は、次のメソッドを使用して sql マッピング構成ファイルで定義するだけで済みます。

<mapper namespace="org.chengzi.mapper.StudentMapper">

    <resultMap id="studentResultMap" type="student">
        <result column="score_english" property="scoreEnglish"/>
        <result column="score_math" property="scoreMath"/>
    </resultMap>
    
    <select id="selectAll" resultMap="studentResultMap">
     select *
        from student;
    </select>
</mapper>

この方法を使用すると、データ テーブルのフィールド名のうち、Java エンティティ クラスの属性とは異なる部分をマッピングするだけで済み、効率が大幅に向上します。resultMap タグの id は一意の識別子として使用され、ステートメントで使用されます。

resultMap では、一般データへのマッピング用と主キー データへのマッピング用の 2 つのタグを使用できます。

プログラムを実行します。

画像-20230129210333422

データ テーブル内のデータはすべて、Java オブジェクトにカプセル化されています。

4. お問い合わせ内容

クライアントでは、多くの場合、データは完全ではなく部分的に表示され、他の部分は通常、詳細を表示する方法で表示する必要があります。このとき、ユーザーが指定された生徒を選択して情報を確認すると、生徒の ID が Java コードに送信され、ユーザー ID を介して生徒のすべての情報が照会されます。

クエリの詳細機能は、次の手順で実装できます。

  • Mapper インターフェースを記述します。
    • パラメータ: ID
    • 戻り値: 学生
  • SQL マッピング ファイルの書き込み
  • テストメソッドを実行する

詳細を照会する場合、id などのパラメーターを渡して、id に従って生徒のすべての情報を照会する必要があることがよくあります。返される結果は 1 つのレコード データのみであるため、カプセル化するだけで済みます。物体。

4.1 インターフェイスメソッドの記述

StudentMapper インターフェイスで id に基づくデータ クエリのメソッドを定義します。

/**
  * 查看详情:根据Id查询
  */
Student selectById(int id);

4.2 SQL文を書く

MyBatisX のクイック ジャンプ機能を使用して、該当する sql マッピング構成ファイルにジャンプすると、ステートメントが自動的に生成され、以前に定義した resultMap を直接使用できます。

<select id="selectById"  resultMap="studentResultMap">
    select *
    from student where id = #{id};
</select>

上記は#{id}後で説明する前に使用したものと同様のパラメーター プレースホルダーです。

4.3 テストメソッドの記述

MyBatisTest クラスで、次のように、すべての学生情報をテストおよびクエリするためのコードを記述します。

@Test
    public void testSelectById() throws IOException {
    
    
        //接收参数
        int id =2;
        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        //4. 执行方法
        Student students = studentMapper.selectById(id);
        System.out.println(students);

        //5. 释放资源
        sqlSession.close();
    }

この時点で、先ほどの全生徒情報のクエリとは異なり、このメソッドのパラメータと戻り値が異なります。Java コードが受け取ったパラメーターを渡すだけで、照会されたデータを Student クラス オブジェクトにカプセル化できます。

操作結果:

画像-20230129212902381

4.4 パラメーターのプレースホルダー

前述のように、sql ステートメントはパラメーター#{xx}のプレースホルダーとして、実行中のログからわかるように、実際には、Java は実行中のプロセス中にパラメーターのプレースホルダーの位置を自動的に に置き換えます。 . 写真に示すように:

画像-20230129213409241

実際、MyBatis のプレースホルダーは に加えて使用すること#{xx}${xx}、これは文字列の綴りのときに sql インジェクションの問題が発生しやすいため、クエリのテーブル名が不明な場合は、一般的に sql ステートメントの from の後に使用されます。

この 2 つの違いは#{xx}、プレースホルダーの最下層がステートメントであるのに対し${xx}、は SQL インジェクションの問題があるステートメントであることです。したがって、MyBatis 開発では前者をパラメーターのプレースホルダーとして使用することをお勧めします。

4.5 parameterType の使用法

Mapper インターフェースのメソッドにパラメーターがある場合、対応する sql マッピング ファイルで parameterType を構成して、パラメーターのデータ型を指定する必要がありますが、この属性は省略できます。省略できる理由は、このパラメータのデータ型が Mapper インターフェース ファイルで定義されているためであることは理解に難くありません。

次のように:

<mapper>   
	<select id="selectById" parameterType="int" resultMap="studentResultMap">
select * from student where id=#{id};
    </select>
</mapper>

4.6 特殊文字の扱い

MyBatis が対応する sql マッピング設定ファイルに sql を書き込むときに、いくつかの特殊文字が表示されます.たとえば、小なり記号を使用すると、ラベルの<部分ます. 写真に示すように:

画像-20230129233235106

MyBatis には、この問題を解決するための対応するメソッドも用意されています。次の 2 つのメソッドを使用できます。

  1. エスケープ文字: 特殊文字が少ない場合に使用
  2. CDATE: 紛らわしい特殊文字がたくさんある場合に使用します

たとえば、エスケープ文字の使用:

画像-20230129234459723

または、CDATA メソッドを使用します。

画像-20230129234642325

コードのオートコンプリート機能を備えた IDE を使用する場合、入力の一部のみをオートコンプリートする必要があります.この方法は、特殊文字が多い場合に使用されます.

5. 複数条件クエリ

クライアントの実際の運用では、複数の条件の同時満足に基づいてデータをクエリすることがよくあります。たとえば、クエリの場合、英語のスコアと数学のスコアが両方とも 60 を超えるすべての学生の情報をクエリします。

ここでの焦点は、SQL ステートメントの書き方です。

クエリの詳細機能は、次の手順で実装できます。

  • Mapper インターフェースを書く
    • パラメータ: すべてのクエリ条件
    • 結果:List<Student>
  • SQL マッピング構成ファイルの書き込み
  • テストメソッドを実行する

5.1 インターフェイスメソッドの記述

StudentMapper インターフェースで複数条件クエリのメソッドを定義するには、インターフェース定義時にパラメータも定義する必要がありますが、MyBatis には複数条件クエリの複数パラメータに対する複数の実装メソッドがあります。

方法 1 :

マッピング構成ファイルでプレースホルダーとして使用する必要がある各パラメーター@Param("参数名称")マークするために使用します。#{参数名称}

List<Student> selectByCondition(@Param("scoreEnglish") int scoreEnglish, @Param("scoreMath") int scoreMath);

方法 2 :

複数のパラメーターをエンティティ オブジェクトにカプセル化し、エンティティ オブジェクトをインターフェイスのメソッド パラメーターとして使用します。このメソッドは、マッピング構成ファイルの SQL で使用する#{内容}場合内部のコンテンツがエンティティ クラスの属性名と一致している必要があります。

List<Student> selectByCondition(Student student);

方法 3 :

複数のパラメーターをマップ コレクションにカプセル化し、マップ コレクションをインターフェイスのメソッド パラメーターとして使用します。このメソッドは、マッピング構成ファイルの SQL で使用する#{内容}場合内部のコンテンツがマップ コレクション内のキーの名前と一致している必要があります。

List<Student> selectByCondition(Map map);

5.2 SQL文を書く

対応するステートメントを StudentMapper.xml ファイルに書き込みます。resultMap も使用されます。例:

<mapper> 
	<select id="selectByCondition" resultMap="studentResultMap">
        select * from student 
                 where score_english > #{scoreEnglish} and score_math > #{scoreMath};
    </select>
</mapper>

5.3 テストメソッドを書く

複合条件クエリでは、Mapper インターフェースを定義する際にパラメーターを設定する方法が 3 通りあるため、ここでの具体的な実行方法も 3 通りの方法に分けられます。

    @Test
    public void testSelectByCondition() throws IOException {
    
    
        //接收参数
        int scoreEnglish=60;
        int scoreMath=60;
        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        //4. 执行方法
        //方法1.使用第一种方法定义参数时使用
        List<Student> students = studentMapper.selectByCondition(scoreEnglish,scoreMath);
        System.out.println(students);
        
        //方法2.使用第二种方法定义参数时使用
        Student student = new Student();
        student.setScoreEnglish(scoreEnglish);
        student.setScoreMath(scoreMath);

        List<Student> students = studentMapper.selectByCondition(student);
        System.out.println(students);
        
        //方法3.使用第三种方法定义参数时使用
        Map map = new HashMap();
        map.put("scoreEnglish" , scoreEnglish);
        map.put("scoreMath" , scoreMath);
        
        List<Student> students = studentMapper.selectByCondition(map);
        System.out.println(students);
        //5. 释放资源
        sqlSession.close();
    }
}

図に示すように、3 つの方法を使用してプログラムを実行すると、結果は同じになります。

画像-20230129224312015

5.4 動的 SQL

上記では、複数条件のクエリで 3 つのパラメーターを設定し、テスト プログラムの実行時に 3 つのパラメーターを渡しました。しかし、実際にはユーザーが各パラメーターに値を入力することはなく、現時点では上記の sql に問題があります。

ユーザーが 2 つのパラメーターを入力すると、SQL ステートメントは次のようになります。

select * from student where score_english > #{scoreEnglish} and score_math > #{scoreMath};

ユーザーが 1 つの条件のみを入力した場合、SQL ステートメントは次のようになります。

select * from student where score_english > #{scoreEnglish} ;

この問題に対して、MyBatis には強力な解決策があります。

  • もしも
  • 選択する(いつ、そうでなければ)
  • トリム (場所、設定)
  • foreach

たとえば、次の方法を使用して解決します。

<select id="selectByCondition" resultMap="studentResultMap">
     select * from student 
     where
        <if test="scoreEnglish !=null">
              score_english > #{scoreEnglish}
        </if>
		<if test="scoreMath !=null">
              and score_math > #{scoreMath}
        </if>

</select>

このメソッドを使用すると、プログラムの実行時に文字列が動的に結合されます. 両方のデータが渡された場合、SQL ステートメントの結合は次のようになります:

画像-20230129231539021

また、ユーザーが後者の値を渡さない場合、プログラムも正常に実行されます。この時点での SQL 文字列は次のとおりです。

画像-20230129231659101

しかし、前者に入力データがなく、後者だけがデータを与えた場合、プログラムはエラーになります。これは、SQL 文字列を接合するときに、where の後に と が表示され、この時点で sql 構文エラーが発生するためです。次のように:

select * from student where and scoreMath > ? ;//语法错误

この問題は、where キーワードを置き換えることができる where タグを使用して解決でき、最初の条件の後の and は動的に削除されます. すべてのパラメーターに値が指定されていない場合、where キーワードは使用されません.

注: この時点で、各条件に and キーワードを追加する必要があります<where>。最初の条件の後の and は動的に削除されます。

この時点で、プログラムは正常に実行され、ユーザーがすべてのパラメーターに値を入力できない可能性があるという問題が解決されます。写真に示すように:

画像-20230129232606376

6. 動的 SQL の単一条件クエリ

クライアントでは、ユーザーが条件付きクエリを選択できる場合がありますが、Java コードでは選択する条件がわからないため、動的 SQL の単一の条件付きクエリを使用する必要があります。

このような要件はchoose(when,otherwise)tagます。choose タグの使用は、Java の Switch ステートメントに似ています。

6.1 インターフェイスメソッドの記述

Mapper インターフェイスで動的 SQL を記述する単一条件クエリ メソッド:

List<Student> selectByConditionSingle(Map map);

6.2 SQL文を書く

次のように、sql マッピング構成ファイルに sql ステートメントを記述します。

<mapper>    
    <select id="selectByConditionSingle" resultMap="studentResultMap">

        select * from student
        <where>
            <choose>
                <when test="scoreEnglish !=null">
                    score_english > #{scoreEnglish}
                </when>
                <when test="scoreMath !=null">
                    score_math > #{scoreMath}
                </when>
                <otherwise>
                    1=1
                </otherwise>
            </choose>
        </where>
    </select>
</mapper>

6.3 テストメソッドを書く

次のように、単体テスト コードを MyBatisTest クラスに記述します。

@Test
    public void testSelectByConditionSingle() throws IOException {
    
    
        //接收参数
        int scoreEnglish=60;
        int scoreMath=60;
        //1. 获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //3. 获取Mapper接口的代理对象
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);

        Map map = new HashMap();
        map.put("scoreEnglish" , scoreEnglish);
        //map.put("scoreMath" , scoreMath);

        List<Student> students = studentMapper.selectByConditionSingle(map);
        System.out.println(students);
        //5. 释放资源
        sqlSession.close();
    }

図に示すように、実行結果は正しいです。

画像-20230130013053973

7. まとめ

この記事は、追加、削除、変更、およびクエリ操作を実装するための MyBatis の開発と構成ファイルの使用の実践的な演習です. 記事が長いため、この記事ではクエリ操作のみを扱います. データベースを操作する最も一般的な方法として、クエリ操作は、習熟するために継続的に練習する必要があります。SQL を記述する場合、大文字の使用は強調されていませんが、大文字を使用することをお勧めします。これは、大文字の使用がより標準化された SQL メソッドであるためです。

書き終えて時間を確認すると、今は午前2時、この記事を書き終えたばかりで、外は異常に静かだった。作成は簡単ではありません。お役に立てば幸いです。最初に気に入って、後で見て、習慣にして、次号でお会いしましょう。

画像-20230130001121015

おすすめ

転載: blog.csdn.net/zhangxia_/article/details/128796222