[Mybatis チュートリアル] 永続層フレームワーク、史上最も完全な Mybatis チュートリアル、プロジェクト開発におけるデータベース操作に Mybatis を使用する方法を説明する 1 つの記事

マイバティスの紹介

MyBatisの歴史

  • MyBatis はもともと、Apache のオープン ソース プロジェクトである iBatis でしたが、2010 年 6 月に、このプロジェクトは Apache Software Foundation によって Google Code に移行されました。開発チームが Google Code に移行したため、iBatis3.x は正式に MyBatis に名前が変更されました。コードは 2013 年 11 月に Github に移行されました
  • iBatis という言葉は、「インターネット」と「アバティス」の組み合わせから来ており、Java をベースにした永続層フレームワークです。 iBatis が提供する永続層フレームワークには、SQL マップとデータ アクセス オブジェクト (DAO) が含まれています。

MyBatisの機能

  1. MyBatis は、カスタマイズされた SQL、ストアド プロシージャ、高度なマッピングをサポートする優れた永続層フレームワークです。
  2. MyBatis は、ほぼすべての JDBC コード、パラメータの手動設定、結果セットの取得を回避します。
  3. MyBatis は、構成とオリジナルのマッピングに単純な XML または注釈を使用し、インターフェースと Java POJO (Plain Old Java Objects、通常の Java オブジェクト) をデータベース内のレコードにマッピングできます。
  4. MyBatis は半自動 ORM (オブジェクト関係マッピング) フレームワークです。

MyBatisのダウンロード

他の永続化レイヤーテクノロジーとの比較

  • JDBC
    • Java コードに SQL が高度な結合で混在しているため、ハードコーディングに内部損傷が発生します。
    • メンテナンスは難しく、実際の開発要件では SQL が変更され、頻繁に修正が行われることが一般的です。
    • コードが長くて開発効率が低い
  • Hibernate と JPA
    • 操作が簡単で開発効率が高い
    • プログラム内の長くて複雑な SQL はフレームワークをバイパスする必要がある
    • 内部で自動生成されるSQLは特別な最適化を行うのが容易ではありません。
    • 完全なマッピングのための完全に自動化されたフレームワークに基づいて、多数のフィールドを持つ POJO を部分的にマッピングすることは困難です。
    • リフレクション操作が多すぎるとデータベースのパフォーマンスが低下する
  • マイバティス
    • 軽量、優れたパフォーマンス
    • SQL と Java のコーディングは分離されており、機能の境界は明確です。 Java コードはビジネスに重点を置き、SQL ステートメントはデータに重点​​を置きます
    • 開発効率は HIbernate よりわずかに低いですが、完全に許容可能です

MyBatis を構築する

開発環境

  • IDE: アイデア 2023.2
  • ビルドツール:Maven 3.5.4
  • MySQL バージョン: MySQL 5.7
  • MyBatis バージョン: MyBatis 3.5.7

Maven プロジェクトを作成する

  • 包装方法: 瓶

  • 依存関係を導入する

    <dependencies>
    	<!-- Mybatis核心 -->
    	<dependency>
    		<groupId>org.mybatis</groupId>
    		<artifactId>mybatis</artifactId>
    		<version>3.5.7</version>
    	</dependency>
    	<!-- junit测试 -->
    	<dependency>
    		<groupId>junit</groupId>
    		<artifactId>junit</artifactId>
    		<version>4.12</version>
    		<scope>test</scope>
    	</dependency>
    	<!-- MySQL驱动 -->
    	<dependency>
    		<groupId>mysql</groupId>
    		<artifactId>mysql-connector-java</artifactId>
    		<version>5.1.3</version>
    		</dependency>
    </dependencies>
    

MyBatisのコア設定ファイルを作成する

名前を付けるのが一般的ですmybatis-config.xml。このファイル名は単なる提案であり、必須ではありません。将来 Spring が統合された後は、この設定ファイルは省略可能ですので、運用時に直接コピー&ペーストすることができます。
コア構成ファイルは主に、データベースに接続するための環境と、MyBatis のグローバル構成情報を構成するために使用されます。
コア構成ファイルは、 src/main/resources ディレクトリ

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE configuration  
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
"http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
	<!--设置连接数据库的环境-->  
	<environments default="development">  
		<environment id="development">  
			<transactionManager type="JDBC"/>  
			<dataSource type="POOLED">  
				<property name="driver" value="com.mysql.cj.jdbc.Driver"/>  
				<!--数据库ip地址(默认为本机localhost)以及端口号(默认端口号3306)以及数据库名称(我的是Mybatis)-->  
				<property name="url" value="jdbc:mysql://localhost:3306/MyBatis"/>  
				<!--数据库用户名-->
				<property name="username" value="root"/>   
				<!-- 数据库密码-->
				<property name="password" value="1234"/>  
			</dataSource>  
		</environment>  
	</environments>  
	<!--引入映射文件-->  
	<mappers>  
		<mapper resource="mappers/UserMapper.xml"/>  
	</mappers>  
</configuration>

マッパーインターフェイスの作成

MyBatis のマッパー インターフェイスは以前の dao と同等です。ただし、違いは、マッパーは単なるインターフェイスであり、実装クラスを提供する必要がないことです。

package com.atguigu.mybatis.mapper;  
  
public interface UserMapper {
    
      
	/**  
	* 添加用户信息  
	*/  
	int insertUser();  
}

MyBatisマッピングファイルを作成する

  • 関連概念: ORM (オブジェクト関係マッピング) オブジェクト関係マッピング。
    • オブジェクト: Javaエンティティクラスオブジェクト
    • リレーショナル: リレーショナル データベース
    • マッピング: 2 つの間の対応関係
Javaの概念 データベースの概念
親切 表面
属性 フィールド/列
物体 レコード/行
  • マッピングファイルの命名規則
    • テーブルに対応するエンティティクラスのクラス名+Mapper.xml
    • 例: テーブル t_user、マップされたエンティティ クラスは User、対応するマッピング ファイルは UserMapper.xml
    • したがって、マッピングファイルはエンティティクラスに相当し、テーブルの操作に相当します。
    • MyBatis マッピング ファイルは、SQL の作成、テーブル内のデータへのアクセスおよび操作に使用されます。
    • MyBatis マッピング ファイルが保存される場所は、src/main/resources/mappers ディレクトリにあります。
  • MyBatis では、データはインターフェイス指向で操作できますが、この 2 つは一貫している必要があります。
    • マッパー インターフェイスの完全なクラス名は、マッピング ファイルの名前空間と一致しています。
    • マッパーインターフェースのメソッドのメソッド名は、マッピングファイルにSQLを記述するラベルのid属性と一致します。
<?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="com.atguigu.mybatis.mapper.UserMapper">  
	<!--int insertUser();-->  
	<insert id="insertUser">  
		insert into t_user values(null,'张三','123',23,'女')  
	</insert>  
</mapper>

junit 経由で機能をテストする

  • SqlSession: Java プログラムとデータベース間のセッションを表します。 (HttpSession は Java プログラムとブラウザ間のセッションです)
  • SqlSessionFactory: SqlSession を「生成」する「ファクトリー」です。
  • ファクトリ パターン: オブジェクトの作成に使用されるプロセスが基本的に固定されている場合、このオブジェクトを作成するための関連コードを「ファクトリ クラス」にカプセル化し、このファクトリ クラスを使用して将来必要なオブジェクトを「生成」できます。
public class UserMapperTest {
    
    
    @Test
    public void testInsertUser() throws IOException {
    
    
        //读取MyBatis的核心配置文件
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        //获取SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        //获取sqlSession,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
        //SqlSession sqlSession = sqlSessionFactory.openSession();
	    //创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交  
		SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //通过代理模式创建UserMapper接口的代理实现类对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句
        int result = userMapper.insertUser();
        //提交事务
        //sqlSession.commit();
        System.out.println("result:" + result);
    }
}
  • 現時点では、トランザクションを手動で送信する必要があります。トランザクションを自動的に送信する場合は、sqlSession オブジェクトを取得するときに SqlSession sqlSession = sqlSessionFactory.openSession(true); を使用し、次のブール型パラメータを渡します。値が true なので、自動的に送信できます

log4jロギング機能を追加

  1. 依存関係を追加する
    <!-- log4j日志 -->
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    </dependency>
    
  2. log4j設定ファイルを追加
    • log4j 構成ファイルの名前は log4j.xml で、src/main/resources ディレクトリに保存されます。
    • ログレベル:FATAL(致命的)>ERROR(エラー)>WARN(警告)>INFO(情報)>DEBUG(デバッグ) 左から右に出力される内容が詳細になっていきます。
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
        <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
            <param name="Encoding" value="UTF-8" />
            <layout class="org.apache.log4j.PatternLayout">
    			<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
            </layout>
        </appender>
        <logger name="java.sql">
            <level value="debug" />
        </logger>
        <logger name="org.apache.ibatis">
            <level value="info" />
        </logger>
        <root>
            <level value="debug" />
            <appender-ref ref="STDOUT" />
        </root>
    </log4j:configuration>
    

コア設定ファイルの詳細な説明

コア構成ファイル内のタグは、固定された順序である必要があります(一部のタグは省略できますが、順序を間違えないようにする必要があります)。
プロパティ、設定、typeAliases、 typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、プラグイン、環境、databaseIdProvider、マッパー

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//MyBatis.org//DTD Config 3.0//EN"
        "http://MyBatis.org/dtd/MyBatis-3-config.dtd">
<configuration>
    <!--引入properties文件,此时就可以${属性名}的方式访问属性值-->
    <properties resource="jdbc.properties"></properties>
    <settings>
        <!--将表中字段的下划线自动转换为驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <typeAliases>
        <!--
        typeAlias:设置某个具体的类型的别名
        属性:
        type:需要设置别名的类型的全类名
        alias:设置此类型的别名,且别名不区分大小写。若不设置此属性,该类型拥有默认的别名,即类名
        -->
        <!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>-->
        <!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="user">
        </typeAlias>-->
        <!--以包为单位,设置改包下所有的类型都拥有默认的别名,即类名且不区分大小写-->
        <package name="com.atguigu.mybatis.bean"/>
    </typeAliases>
    <!--
    environments:设置多个连接数据库的环境
    属性:
	    default:设置默认使用的环境的id
    -->
    <environments default="mysql_test">
        <!--
        environment:设置具体的连接数据库的环境信息
        属性:
	        id:设置环境的唯一标识,可通过environments标签中的default设置某一个环境的id,表示默认使用的环境
        -->
        <environment id="mysql_test">
            <!--
            transactionManager:设置事务管理方式
            属性:
	            type:设置事务管理方式,type="JDBC|MANAGED"
	            type="JDBC":设置当前环境的事务管理都必须手动处理
	            type="MANAGED":设置事务被管理,例如spring中的AOP
            -->
            <transactionManager type="JDBC"/>
            <!--
            dataSource:设置数据源
            属性:
	            type:设置数据源的类型,type="POOLED|UNPOOLED|JNDI"
	            type="POOLED":使用数据库连接池,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建
	            type="UNPOOLED":不使用数据库连接池,即每次使用连接都需要重新创建
	            type="JNDI":调用上下文中的数据源
            -->
            <dataSource type="POOLED">
                <!--设置驱动类的全类名-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--设置连接数据库的连接地址-->
                <property name="url" value="${jdbc.url}"/>
                <!--设置连接数据库的用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--设置连接数据库的密码-->
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--引入映射文件-->
    <mappers>
        <!-- <mapper resource="UserMapper.xml"/> -->
        <!--
        以包为单位,将包下所有的映射文件引入核心配置文件
        注意:
			1. 此方式必须保证mapper接口和mapper映射文件必须在相同的包下
			2. mapper接口要和mapper映射文件的名字一致
        -->
        <package name="com.atguigu.mybatis.mapper"/>
    </mappers>
</configuration>
  • ここに画像の説明を挿入します

デフォルトのタイプのエイリアス

ここに画像の説明を挿入します

ここに画像の説明を挿入します

MyBatis の追加、削除、変更、クエリ

  1. に追加
    <!--int insertUser();-->
    <insert id="insertUser">
    	insert into t_user values(null,'admin','123456',23,'男','[email protected]')
    </insert>
    
  2. 消去
    <!--int deleteUser();-->
    <delete id="deleteUser">
        delete from t_user where id = 6
    </delete>
    
  3. 改訂
    <!--int updateUser();-->
    <update id="updateUser">
        update t_user set username = '张三' where id = 5
    </update>
    
  4. エンティティクラスオブジェクトをクエリする
    <!--User getUserById();-->  
    <select id="getUserById" resultType="com.atguigu.mybatis.bean.User">  
    	select * from t_user where id = 2  
    </select>
    
  5. クエリコレクション
    <!--List<User> getUserList();-->
    <select id="getUserList" resultType="com.atguigu.mybatis.bean.User">
    	select * from t_user
    </select>
    
  • 知らせ:

    1. クエリのラベル選択では、エンティティ クラスとデータベース テーブル間のマッピング関係を設定するために使用される属性 resultType または resultMap を設定する必要があります。
      • resultType: 自動マッピング。属性名がテーブル内のフィールド名と一致する場合に使用されます。
      • resultMap: カスタム マッピング。1 対多または多対 1 の状況、またはフィールド名と属性名が一致しない場合に使用されます。
    2. 複数のデータがクエリされた場合、エンティティ クラスは戻り値として使用できず、コレクションのみが使用され、それ以外の場合は TooManyResultsException がスローされますが、クエリされたデータが 1 つだけの場合は、エンティティ クラスまたはコレクションを戻り値として使用できます。戻り値。

MyBatisがパラメータ値を取得する2つの方法(ポイント)

  • MyBatis では、パラメータ値を取得する方法として ${} と #{} の 2 つの方法がありますが、SQL インジェクションのリスクを防ぐために #{} を使用することをお勧めします。
  • ${} の本質は文字列の連結であり、#{} の本質はプレースホルダーの割り当てです。
  • ${} は文字列のスプライシングを使用して SQL を結合します。値を文字列型または日付型のフィールドに割り当てる場合は、一重引用符を手動で追加する必要があります。ただし、#{} はプレースホルダの割り当てを使用して SQL を結合します。この場合、文字列型や日付型のフィールドに値を代入する際に、シングルクォーテーションを自動で付加することができます。

単一リテラル型のパラメータ

  • マッパー インターフェイスのメソッド パラメーターが単一のリテラル型である場合、${} と #{} を使用して、任意の名前のパラメーターの値を取得できます (名前を認識することが最善です)。手動で追加します。
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">
	select * from t_user where username = #{username}
</select>
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">  
	select * from t_user where username = '${username}'  
</select>

複数のリテラル型のパラメータ

  • マッパー インターフェイスに複数のメソッド パラメータがある場合、MyBatis はこれらのパラメータをマップ コレクションに自動的に配置します。

    1. arg0、arg1... をキーとして使用し、パラメータを値として使用します。
    2. param1、param2... をキーとして使用し、パラメータを値として使用します。
  • したがって、${} と #{} を介してマップ コレクションのキーにアクセスするだけで、対応する値を取得できます。${} は一重引用符で囲んで手動で追加する必要があることに注意してください。

  • arg または param を使用できますが、arg は arg0 から始まり、param は param1 から始まることに注意してください。

<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">  
	select * from t_user where username = #{arg0} and password = #{arg1}  
</select>
<!--User checkLogin(String username,String password);-->
<select id="checkLogin" resultType="User">
	select * from t_user where username = '${param1}' and password = '${param2}'
</select>

マップコレクションタイプのパラメータ

  • マッパー インターフェイスのメソッドに複数のパラメータが必要な場合は、マップ コレクションを手動で作成できます。これらのデータをマップに配置するには、${} と #{} を介してマップ コレクションのキーにアクセスし、対応するデータを取得するだけです。 data。値。${} は一重引用符で囲んで手動で追加する必要があることに注意してください。
<!--User checkLoginByMap(Map<String,Object> map);-->
<select id="checkLoginByMap" resultType="User">
	select * from t_user where username = #{username} and password = #{password}
</select>
@Test
public void checkLoginByMap() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
	Map<String,Object> map = new HashMap<>();
	map.put("usermane","admin");
	map.put("password","123456");
	User user = mapper.checkLoginByMap(map);
	System.out.println(user);
}

エンティティクラスタイプのパラメータ

  • マッパー インターフェイスのメソッド パラメーターがエンティティ クラス オブジェクトの場合、${} と #{} を使用して、エンティティ クラス オブジェクトの属性名にアクセスすることで属性値を取得できます。${} は手動で追加する必要があることに注意してください一重引用符で囲みます。
<!--int insertUser(User user);-->
<insert id="insertUser">
	insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
</insert>
@Test
public void insertUser() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
	User user = new User(null,"Tom","123456",12,"男","[email protected]");
	mapper.insertUser(user);
}

@Param を使用してパラメータを識別する

  • マッパー インターフェイスのメソッド パラメータは @Param アノテーションによって識別でき、この時点でこれらのパラメータはマップ コレクションに配置されます。

    1. @Param アノテーションの value 属性値をキーとして使用し、パラメーターを値として使用します。
    2. param1、param2... をキーとして使用し、パラメータを値として使用します。
  • ${} と #{} を介してマップ コレクションのキーにアクセスするだけで、対応する値を取得できます。${} は一重引用符で囲んで手動で追加する必要があることに注意してください。

<!--User CheckLoginByParam(@Param("username") String username, @Param("password") String password);-->
    <select id="CheckLoginByParam" resultType="User">
        select * from t_user where username = #{username} and password = #{password}
    </select>
@Test
public void checkLoginByParam() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
	mapper.CheckLoginByParam("admin","123456");
}

要約する

  • 2 つの状況に応じて処理することをお勧めします

    1. エンティティクラスタイプのパラメータ
    2. @Param を使用してパラメータを識別する

MyBatisの各種クエリ機能

  1. クエリされるデータが 1 つだけの場合は、次を使用できます。
    1. エンティティクラスオブジェクトが受け取る
    2. リストコレクションが受信する
    3. マップ収集の受信、結果{password=123456, sex=男, id=1, age=23, username=admin}
  2. クエリされたデータが複数ある場合、エンティティ クラス オブジェクトを使用してデータを受信することはできず、TooManyResultsException がスローされます。
    1. エンティティクラスタイプのLStコレクションを受信しました
    2. マップタイプが受け取るリストコレクション
    3. マッパーインターフェースのメソッドに @MapKey アノテーションを追加します。

エンティティクラスオブジェクトをクエリする

/**
 * 根据用户id查询用户信息
 * @param id
 * @return
 */
User getUserById(@Param("id") int id);
<!--User getUserById(@Param("id") int id);-->
<select id="getUserById" resultType="User">
	select * from t_user where id = #{id}
</select>

リストコレクションをクエリする

/**
 * 查询所有用户信息
 * @return
 */
List<User> getUserList();
<!--List<User> getUserList();-->
<select id="getUserList" resultType="User">
	select * from t_user
</select>

単一データのクエリ

/**  
 * 查询用户的总记录数  
 * @return  
 * 在MyBatis中,对于Java中常用的类型都设置了类型别名  
 * 例如:java.lang.Integer-->int|integer  
 * 例如:int-->_int|_integer  
 * 例如:Map-->map,List-->list  
 */  
int getCount();
<!--int getCount();-->
<select id="getCount" resultType="_integer">
	select count(id) from t_user
</select>

データの一部をマップ コレクションとしてクエリする

/**  
 * 根据用户id查询用户信息为map集合  
 * @param id  
 * @return  
 */  
Map<String, Object> getUserToMap(@Param("id") int id);
<!--Map<String, Object> getUserToMap(@Param("id") int id);-->
<select id="getUserToMap" resultType="map">
	select * from t_user where id = #{id}
</select>
<!--结果:{password=123456, sex=男, id=1, age=23, username=admin}-->

複数のデータをマップ コレクションとしてクエリする

方法 1

/**  
 * 查询所有用户信息为map集合  
 * @return  
 * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取  
 */  
List<Map<String, Object>> getAllUserToMap();
<!--Map<String, Object> getAllUserToMap();-->  
<select id="getAllUserToMap" resultType="map">  
	select * from t_user  
</select>
<!--
	结果:
	[{password=123456, sex=男, id=1, age=23, username=admin},
	{password=123456, sex=男, id=2, age=23, username=张三},
	{password=123456, sex=男, id=3, age=23, username=张三}]
-->

方法 2

/**
 * 查询所有用户信息为map集合
 * @return
 * 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合
 */
@MapKey("id")
Map<String, Object> getAllUserToMap();
<!--Map<String, Object> getAllUserToMap();-->
<select id="getAllUserToMap" resultType="map">
	select * from t_user
</select>
<!--
	结果:
	{
	1={password=123456, sex=男, id=1, age=23, username=admin},
	2={password=123456, sex=男, id=2, age=23, username=张三},
	3={password=123456, sex=男, id=3, age=23, username=张三}
	}
-->

特殊なSQLの実行

ファジークエリ

/**
 * 根据用户名进行模糊查询
 * @param username 
 * @return java.util.List<com.atguigu.mybatis.pojo.User>
 * @date 2022/2/26 21:56
 */
List<User> getUserByLike(@Param("username") String username);
<!--List<User> getUserByLike(@Param("username") String username);-->
<select id="getUserByLike" resultType="User">
	<!--select * from t_user where username like '%${mohu}%'-->  
	<!--select * from t_user where username like concat('%',#{mohu},'%')-->  
	select * from t_user where username like "%"#{mohu}"%"
</select>
  • その中でselect * from t_user where username like "%"#{mohu}"%" が最もよく使用されます

一括削除

  • は ${} のみを使用できます。#{} が使用された場合、解析された SQL ステートメントは delete from t_user where id in ('1,2,3') であるため、 1,2,3 は全体としてみなされます。 、ID 1,2,3 のデータのみが削除されます。正しいステートメントは delete from t_user where id in (1,2,3) または です。delete from t_user where id in ('1','2','3')
/**
 * 根据id批量删除
 * @param ids 
 * @return int
 * @date 2022/2/26 22:06
 */
int deleteMore(@Param("ids") String ids);
<delete id="deleteMore">
	delete from t_user where id in (${ids})
</delete>
//测试类
@Test
public void deleteMore() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
	int result = mapper.deleteMore("1,2,3,8");
	System.out.println(result);
}

動的に設定されるテーブル名

  • テーブル名は一重引用符で囲むことができないため、${} のみを使用できます。
/**
 * 查询指定表中的数据
 * @param tableName 
 * @return java.util.List<com.atguigu.mybatis.pojo.User>
 * @date 2022/2/27 14:41
 */
List<User> getUserByTable(@Param("tableName") String tableName);
<!--List<User> getUserByTable(@Param("tableName") String tableName);-->
<select id="getUserByTable" resultType="User">
	select * from ${tableName}
</select>

自動インクリメントされる主キーを取得する関数を追加

  • 使用するシーン
    • t_clazz(clazz_id,clazz_name)
    • t_student(student_id,student_name,clazz_id)
    1. クラス情報を追加する
    2. 新しく追加されたクラスのIDを取得します
    3. 生徒をクラスに割り当てる、つまり、特定の学校のクラス ID を新しく追加したクラスの ID に変更します。
  • Mapper.xml に 2 つのプロパティを設定します
    • useGeneratedKeys: 自動インクリメントを使用するように主キーを設定します。
    • keyProperty: 追加、削除、および変更の統一された戻り値は影響を受ける行の数であるため、取得された自動インクリメントされた主キーは、送信されたパラメーターのユーザー オブジェクトの特定の属性にのみ配置できます。
/**
 * 添加用户信息
 * @param user 
 * @date 2022/2/27 15:04
 */
void insertUser(User user);
<!--void insertUser(User user);-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
	insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})
</insert>
//测试类
@Test
public void insertUser() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
	User user = new User(null, "ton", "123", 23, "男", "[email protected]");
	mapper.insertUser(user);
	System.out.println(user);
	//输出:user{id=10, username='ton', password='123', age=23, sex='男', email='[email protected]'},自增主键存放到了user的id属性中
}

カスタムマッピング結果マップ

resultMap はフィールドと属性間のマッピング関係を処理します。

  • resultMap: カスタム マッピングを設定します。
    • 属性:
      • id: カスタム マッピングの一意の識別子を表します。これを繰り返すことはできません。
      • type: クエリされたデータにマップされるエンティティ クラスのタイプ
    • サブタグ:
      • id:主キーのマッピング関係を設定します
      • 結果: 共通フィールドのマッピング関係を設定します
      • サブタグの属性:
        • property: マッピング関係のエンティティクラスに属性名を設定します
        • 列: マッピング関係のテーブルのフィールド名を設定します
  • フィールド名がエンティティ クラスの属性名と一致しない場合は、resultMap を使用してカスタム マッピングを設定できます。フィールド名と属性名が同じ属性であってもマッピングする必要があります。つまり、すべての属性をリストする必要があります。
<resultMap id="empResultMap" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
</resultMap>
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultMap="empResultMap">
	select * from t_emp
</select>
  • フィールド名がエンティティ クラスの属性名と一致しないが、フィールド名がデータベースの規則に準拠しており (_ を使用)、エンティティ クラスの属性名が Java の規則に準拠している (キャメル ケースを使用) 場合。このとき、エンティティクラス内のフィールド名と属性のマッピング関係は、次の 2 つの方法でも扱うことができます。

    1. フィールドに別名を付けると、フィールドがエンティティ クラスの属性名と一致するようにすることができます。
      <!--List<Emp> getAllEmp();-->
      <select id="getAllEmp" resultType="Emp">
      	select eid,emp_name empName,age,sex,email from t_emp
      </select>
      
    2. MyBatis のコア構成ファイルの setting タグにグローバル構成情報 mapUnderscoreToCamelCase を設定できます。これにより、_ タイプのフィールド名をキャメルケースに自動的に変換できます。例: field name user_name、mapUnderscoreToCamelCase が設定されている場合、フィールド名は userName に変換されます。 コア構成ファイルの詳細な説明
    「」

多対一マッピング処理

従業員情報とその従業員に対応する部門情報を問い合わせる

public class Emp {
    
      
	private Integer eid;  
	private String empName;  
	private Integer age;  
	private String sex;  
	private String email;  
	private Dept dept;
	//...构造器、get、set方法等
}

カスケードモードでのマッピング関係の処理

<resultMap id="empAndDeptResultMapOne" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
	<result property="dept.did" column="did"></result>
	<result property="dept.deptName" column="dept_name"></result>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapOne">
	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

アソシエーションを使用してマッピング関係を処理する

  • 関連付け: 多対 1 のマッピング関係を処理します。
  • property: マッピング関係の複数のペアを処理する必要があるプロパティ名
  • javaType: この属性のタイプ
<resultMap id="empAndDeptResultMapTwo" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
	<association property="dept" javaType="Dept">
		<id property="did" column="did"></id>
		<result property="deptName" column="dept_name"></result>
	</association>
</resultMap>
<!--Emp getEmpAndDept(@Param("eid")Integer eid);-->
<select id="getEmpAndDept" resultMap="empAndDeptResultMapTwo">
	select * from t_emp left join t_dept on t_emp.eid = t_dept.did where t_emp.eid = #{eid}
</select>

ステップバイステップのクエリ

1. 従業員情報のクエリ
  • select: 分散クエリ用SQLの一意の識別子(namespace.SQLIdまたはマッパーインターフェースの完全なクラス名。メソッド名)を設定します。
  • 列: ステップバイステップクエリの条件を設定します
//EmpMapper里的方法
/**
 * 通过分步查询,员工及所对应的部门信息
 * 分步查询第一步:查询员工信息
 * @param  
 * @return com.atguigu.mybatis.pojo.Emp
 * @date 2022/2/27 20:17
 */
Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);
<resultMap id="empAndDeptByStepResultMap" type="Emp">
	<id property="eid" column="eid"></id>
	<result property="empName" column="emp_name"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
	<result property="email" column="email"></result>
	<association property="dept"
				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
				 column="did"></association>
</resultMap>
<!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
	select * from t_emp where eid = #{eid}
</select>
2. 部門情報の問い合わせ
//DeptMapper里的方法
/**
 * 通过分步查询,员工及所对应的部门信息
 * 分步查询第二步:通过did查询员工对应的部门信息
 * @param
 * @return com.atguigu.mybatis.pojo.Emp
 * @date 2022/2/27 20:23
 */
Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);
<!--此处的resultMap仅是处理字段和属性的映射关系-->
<resultMap id="EmpAndDeptByStepTwoResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
</resultMap>
<!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
<select id="getEmpAndDeptByStepTwo" resultMap="EmpAndDeptByStepTwoResultMap">
	select * from t_dept where did = #{did}
</select>

1対多のマッピング処理

public class Dept {
    
    
    private Integer did;
    private String deptName;
    private List<Emp> emps;
	//...构造器、get、set方法等
}

コレクション

  • コレクション: 1 対多のマッピング関係を処理するために使用されます。
  • ofType: この属性が対応するコレクションに格納されているデータのタイプを示します。
<resultMap id="DeptAndEmpResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
	<collection property="emps" ofType="Emp">
		<id property="eid" column="eid"></id>
		<result property="empName" column="emp_name"></result>
		<result property="age" column="age"></result>
		<result property="sex" column="sex"></result>
		<result property="email" column="email"></result>
	</collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") Integer did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmpResultMap">
	select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

ステップバイステップのクエリ

1. 部門情報の問い合わせ
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第一步:查询部门信息
 * @param did 
 * @return com.atguigu.mybatis.pojo.Dept
 * @date 2022/2/27 22:04
 */
Dept getDeptAndEmpByStepOne(@Param("did") Integer did);
<resultMap id="DeptAndEmpByStepOneResultMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="deptName" column="dept_name"></result>
	<collection property="emps"
				select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
				column="did"></collection>
</resultMap>
<!--Dept getDeptAndEmpByStepOne(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepOne" resultMap="DeptAndEmpByStepOneResultMap">
	select * from t_dept where did = #{did}
</select>
2. 部門 ID に基づいて部門内のすべての従業員を照会します。
/**
 * 通过分步查询,查询部门及对应的所有员工信息
 * 分步查询第二步:根据部门id查询部门中的所有员工
 * @param did
 * @return java.util.List<com.atguigu.mybatis.pojo.Emp>
 * @date 2022/2/27 22:10
 */
List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);
<!--List<Emp> getDeptAndEmpByStepTwo(@Param("did") Integer did);-->
<select id="getDeptAndEmpByStepTwo" resultType="Emp">
	select * from t_emp where did = #{did}
</select>

遅延読み込み

  • ステップバイステップ クエリの利点: 遅延読み込みを実現できますが、グローバル構成情報をコア構成ファイルに設定する必要があります。
    • LazyLoadingEnabled: 遅延ロード用のグローバル スイッチ。有効にすると、関連するすべてのオブジェクトが遅延してロードされます。
    • activeLazyLoading: オンにすると、メソッド呼び出しによってオブジェクトのすべてのプロパティが読み込まれます。それ以外の場合、各プロパティはオンデマンドでロードされます
  • このとき、オンデマンドロードが実現され、どのようなデータを取得しても、対応するSQLのみが実行されます。現時点では、現在のステップバイステップ クエリで、関連付けとコレクションの fetchType 属性を使用して遅延読み込みを使用するかどうかを設定できます ( fetchType="lazy (遅延読み込み) | 熱心な (即時読み込み)")。
<settings>
	<!--开启延迟加载-->
	<setting name="lazyLoadingEnabled" value="true"/>
</settings>
@Test
public void getEmpAndDeptByStepOne() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	Emp emp = mapper.getEmpAndDeptByStepOne(1);
	System.out.println(emp.getEmpName());
}
  • 遅延読み込みをオフにすると、両方の SQL ステートメントが実行されます。

  • ここに画像の説明を挿入します

  • 遅延読み込みを有効にし、emp を取得するための SQL ステートメントのみを実行します。
    ここに画像の説明を挿入します

@Test
public void getEmpAndDeptByStepOne() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	Emp emp = mapper.getEmpAndDeptByStepOne(1);
	System.out.println(emp.getEmpName());
	System.out.println("----------------");
	System.out.println(emp.getDept());
}
  • これをオンにすると、dept をクエリする場合にのみ、対応する SQL ステートメントが呼び出されます。

  • ここに画像の説明を挿入します

  • fetchType: グローバル遅延読み込みが有効な場合、この属性 fetchType="lazy (遅延読み込み)|eager (即時読み込み)" を通じて遅延読み込みの効果を手動で制御できます。

    <resultMap id="empAndDeptByStepResultMap" type="Emp">
    	<id property="eid" column="eid"></id>
    	<result property="empName" column="emp_name"></result>
    	<result property="age" column="age"></result>
    	<result property="sex" column="sex"></result>
    	<result property="email" column="email"></result>
    	<association property="dept"
    				 select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
    				 column="did"
    				 fetchType="lazy"></association>
    </resultMap>
    

動的SQL

  • Mybatisフレームワークの動的SQL技術は、SQL文を特定の条件に従って動的に組み立てる機能であり、その存在目的は、SQL文の文字列を結合する際の問題点を解決することです。

もし

  • ifタグはtest属性の式(つまり渡されたデータ)で判断でき、式の結果がtrueの場合はタグの内容が実行され、それ以外の場合はタグの内容は実行されません。実行されました。
  • whereの後に定数成立条件を追加1=1
    • この定数成立条件はクエリ結果には影響しません。
    • This1=1 は、and ステートメントを結合するために使用できます。たとえば、empName が null の場合です。
      • 定数成立条件を付加しない場合のSQL文はselect * from t_emp where and age = ? and sex = ? and email = ?となります。このとき、whereとが併用されます。 and 、SQL ステートメントはエラーを報告します
      • 定数条件が追加された場合、SQL ステートメントはselect * from t_emp where 1= 1 and age = ? and sex = ? and email = ?となり、エラーは報告されません
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select * from t_emp where 1=1
	<if test="empName != null and empName !=''">
		and emp_name = #{empName}
	</if>
	<if test="age != null and age !=''">
		and age = #{age}
	</if>
	<if test="sex != null and sex !=''">
		and sex = #{sex}
	</if>
	<if test="email != null and email !=''">
		and email = #{email}
	</if>
</select>

どこ

  • where と if は通常一緒に使用されます。
    • where タグ内の if 条件がいずれも満たされない場合、where タグは機能しません。つまり、where キーワードは追加されません。
    • where タグの if 条件が満たされると、where タグは where キーワードを自動的に追加し、条件の先頭にある冗長な および/またはを削除します。
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select * from t_emp
	<where>
		<if test="empName != null and empName !=''">
			emp_name = #{empName}
		</if>
		<if test="age != null and age !=''">
			and age = #{age}
		</if>
		<if test="sex != null and sex !=''">
			and sex = #{sex}
		</if>
		<if test="email != null and email !=''">
			and email = #{email}
		</if>
	</where>
</select>
  • 注: where タグでは、条件の冗長および/または後を削除できません。

    <!--这种用法是错误的,只能去掉条件前面的and/or,条件后面的不行-->
    <if test="empName != null and empName !=''">
    emp_name = #{empName} and
    </if>
    <if test="age != null and age !=''">
    	age = #{age}
    </if>
    

トリム

  • トリムはタグ内のコンテンツを削除または追加するために使用されます
  • 共通のプロパティ
    • prefix: トリムタグのコンテンツの前にコンテンツを追加します。
    • suffix: トリムタグのコンテンツの後にコンテンツを追加します。
    • prefixOverrides: トリムタグ内のコンテンツの前にある特定のコンテンツを削除します
    • suffixOverrides: トリムタグ内のコンテンツの後の特定のコンテンツを削除します
  • トリム内のどのタグも条件を満たさない場合、トリム タグは何も効果がありません。select * from t_emp
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select * from t_emp
	<trim prefix="where" suffixOverrides="and|or">
		<if test="empName != null and empName !=''">
			emp_name = #{empName} and
		</if>
		<if test="age != null and age !=''">
			age = #{age} and
		</if>
		<if test="sex != null and sex !=''">
			sex = #{sex} or
		</if>
		<if test="email != null and email !=''">
			email = #{email}
		</if>
	</trim>
</select>
//测试类
@Test
public void getEmpByCondition() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
	List<Emp> emps= mapper.getEmpByCondition(new Emp(null, "张三", null, null, null, null));
	System.out.println(emps);
}

ここに画像の説明を挿入します

選択する、いつ、そうでない場合

  • choose、when、otherwiseに相当if...else if..else
  • 少なくとも 1 つ必要な場合、それ以外の場合は最大 1 つ必要です
<select id="getEmpByChoose" resultType="Emp">
	select * from t_emp
	<where>
		<choose>
			<when test="empName != null and empName != ''">
				emp_name = #{empName}
			</when>
			<when test="age != null and age != ''">
				age = #{age}
			</when>
			<when test="sex != null and sex != ''">
				sex = #{sex}
			</when>
			<when test="email != null and email != ''">
				email = #{email}
			</when>
			<otherwise>
				did = 1
			</otherwise>
		</choose>
	</where>
</select>
@Test
public void getEmpByChoose() {
    
    
	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
	List<Emp> emps = mapper.getEmpByChoose(new Emp(null, "张三", 23, "男", "[email protected]", null));
	System.out.println(emps);
}

ここに画像の説明を挿入します

  • if a else if b else if c else dと同等で、そのうちの 1 つだけが実行されます

フォーリーチ

  • 属性:

    • collection: ループする配列またはコレクションを設定します。
    • item: コレクションまたは配列内の各データを表します
    • separator: ループ本体間のセパレータを設定します。デフォルトではセパレータの前後にスペースがあります。,
    • open: foreachタグにコンテンツの開始文字を設定します。
    • close: foreachタグにコンテンツの終了文字を設定します。
  • 一括削除

    <!--int deleteMoreByArray(Integer[] eids);-->
    <delete id="deleteMoreByArray">
    	delete from t_emp where eid in
    	<foreach collection="eids" item="eid" separator="," open="(" close=")">
    		#{eid}
    	</foreach>
    </delete>
    
    @Test
    public void deleteMoreByArray() {
          
          
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	int result = mapper.deleteMoreByArray(new Integer[]{
          
          6, 7, 8, 9});
    	System.out.println(result);
    }
    

    ここに画像の説明を挿入します

  • バッチで追加

    <!--int insertMoreByList(@Param("emps") List<Emp> emps);-->
    <insert id="insertMoreByList">
    	insert into t_emp values
    	<foreach collection="emps" item="emp" separator=",">
    		(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
    	</foreach>
    </insert>
    
    @Test
    public void insertMoreByList() {
          
          
    	SqlSession sqlSession = SqlSessionUtils.getSqlSession();
    	DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
    	Emp emp1 = new Emp(null,"a",1,"男","[email protected]",null);
    	Emp emp2 = new Emp(null,"b",1,"男","[email protected]",null);
    	Emp emp3 = new Emp(null,"c",1,"男","[email protected]",null);
    	List<Emp> emps = Arrays.asList(emp1, emp2, emp3);
    	int result = mapper.insertMoreByList(emps);
    	System.out.println(result);
    }
    

    ここに画像の説明を挿入します

SQLフラグメント

  • SQL フラグメントはパブリック SQL フラグメントを記録し、それが使用される include タグを通じてそれを導入できます。
  • SQL フラグメントの宣言:<sql>タグ
<sql id="empColumns">eid,emp_name,age,sex,email</sql>
  • SQL フラグメントの引用:<include>タグ
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
	select <include refid="empColumns"></include> from t_emp
</select>

MyBatis キャッシュ

MyBatis の 1 次キャッシュ

  • 1 次キャッシュは SqlSession レベルにあります。同じ SqlSession を通じてクエリされたデータはキャッシュされます。次回同じデータをクエリするとき、そのデータはキャッシュから直接取得され、データベースから再度アクセスされることはありません。

  • 一次キャッシュが無効になる 4 つの状況:

    1. 異なる SqlSession は異なる 1 次キャッシュに対応します
    2. 同じ SqlSession ですが、クエリ条件が異なります
    3. 追加、削除、または変更操作は、同じ SqlSession の 2 つのクエリ中に実行されました。
    4. キャッシュは、同じ SqlSession での 2 つのクエリ中に手動でクリアされました。

MyBatis 2次キャッシュ

  • 2 番目のキャッシュは SqlSessionFactory レベルにあり、同じ SqlSessionFactory を通じて作成された SqlSession クエリの結果がキャッシュされ、その後同じクエリ ステートメントが再度実行されると、結果がキャッシュから取得されます。

  • 2次キャッシュを有効にする条件

    1. コア構成ファイルで、グローバル構成属性cacheEnabled="true"を設定します。デフォルトはtrueであり、設定する必要はありません。
    2. マッピングファイルにラベルを設定する
    3. 2 次キャッシュは、SqlSession が閉じられるかコミットされた後も有効である必要があります。
    4. クエリ データによって変換されたエンティティ クラス タイプはシリアル化インターフェイスを実装する必要があります
  • 2 次キャッシュの無効化: 2 つのクエリ間で追加、削除、および変更を実行すると、1 次キャッシュと 2 次キャッシュの両方が同時に無効になります。

2次キャッシュ関連の設定

  • マッパー構成ファイルに追加されたキャッシュ タグは、いくつかのプロパティを設定できます。
  • エビクション属性: キャッシュのリサイクル戦略
    • LRU (最も最近使用されていない) – 最も長い間使用されていないオブジェクトを削除します。
    • FIFO (先入れ先出し) – キャッシュに入った順序でオブジェクトを削除します。
    • SOFT – ソフト参照: ガベージ コレクターのステータスとソフト参照ルールに基づいてオブジェクトを削除します。
    • WEAK – 弱参照: ガベージ コレクターの状態と弱参照ルールに基づいて、より積極的にオブジェクトを削除します。
    • デフォルトはLRUです
  • flashInterval 属性: リフレッシュ間隔 (ミリ秒単位)
    • デフォルトは設定されていません。つまり、更新間隔はありません。キャッシュは、ステートメント (追加、削除、変更) が呼び出された場合にのみ更新されます。
  • サイズ属性: 参照の数、正の整数
    • キャッシュに保存できるオブジェクトの最大数を表します。大きすぎると、メモリ オーバーフローが発生する可能性があります。
  • readOnly 属性: 読み取り専用、true/false
    • true: 読み取り専用キャッシュ; すべての呼び出し元にキャッシュ オブジェクトの同じインスタンスを返します。したがって、これらのオブジェクトは変更できません。これにより、パフォーマンスに重要な利点がもたらされます。
    • false: 読み取りおよび書き込みキャッシュ。(シリアル化を介して) キャッシュ オブジェクトのコピーを返します。これは遅いですが安全なので、デフォルトは false です。

MyBatis キャッシュ クエリの順序

  • 2 次キャッシュには、他のプログラムによって検出され、直接使用できるデータが存在する可能性があるため、最初に 2 次キャッシュにクエリを実行します。
  • 2 次キャッシュにヒットがない場合は、1 次キャッシュを再度クエリします。
  • 一次キャッシュにヒットがない場合は、データベースにクエリを実行します。
  • SqlSession が閉じられると、1 次キャッシュ内のデータが 2 次キャッシュに書き込まれます。

サードパーティのキャッシュ EHCache を統合 (理解)

依存関係を追加する

<!-- Mybatis EHCache整合包 -->
<dependency>
	<groupId>org.mybatis.caches</groupId>
	<artifactId>mybatis-ehcache</artifactId>
	<version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.2.3</version>
</dependency>

各jarパッケージの機能

jarパッケージ名 効果
mybatis-ehcache Mybatis と EHCache の統合パッケージ
ehcache EHCache コア パッケージ
slf4j-api SLF4J ログポータルバンドル
ログバッククラシック SLF4J ファサード インターフェイスの特定の実装をサポートします。

EHCache 構成ファイル ehcache.xml を作成する

  • 名前を呼ばれなければなりませんehcache.xml
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!-- 磁盘保存路径 -->
    <diskStore path="D:\atguigu\ehcache"/>
    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

2次キャッシュのタイプを設定する

  • xxxMapper.xml ファイルで 2 次キャッシュ タイプを設定します。
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

ログバックログを追加

  • SLF4J が存在する場合、単純なログとしての log4j は無効になるため、ログを出力するには SLF4J logback の特定の実装を使用する必要があります。ログバック設定ファイルを作成しますlogback.xml。名前は固定されており、変更できません
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="DEBUG">
        <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
        <appender-ref ref="STDOUT" />
    </root>
    <!-- 根据特殊需求指定局部日志级别 -->
    <logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>

EHCache 構成ファイルの説明

属性名 それは必要ですか 効果
maxElementsInMemory はい メモリにキャッシュされる要素の最大数
maxElementsOnDisk はい ディスク上にキャッシュされる要素の最大数 (0 が無限を意味する場合)
永遠の はい キャッシュされた要素が期限切れにならないかどうかを設定します。 true の場合、キャッシュされたデータは常に有効ですが、false の場合、timeToIdleSeconds と timeToLiveSeconds に基づいて判断する必要があります。
オーバーフローからディスクへ はい メモリ バッファがオーバーフローしたときに、期限切れの要素をディスクにキャッシュするかどうかを設定します
アイドルまでの時間秒 いいえ EhCache にキャッシュされたデータへの 2 回のアクセス間の時間が timeToIdleSeconds 属性の値を超えると、データは削除されます。デフォルト値は 0 で、アイドル時間が無限であることを意味します。
生存時間秒 いいえ キャッシュ要素の有効期間。デフォルトは 0 です。つまり、要素の生存時間は無限です。
ディスクスプールバッファサイズMB いいえ DiskStore(ディスクキャッシュ)のキャッシュ領域サイズ。デフォルトは 30MB です。各キャッシュには独自のバッファーが必要です
ディスク永続的 いいえ VM の再起動時にディスクが EhCache にデータを保存できるようにするかどうか。デフォルトは false です。
ディスクExpiryThreadIntervalSeconds いいえ ディスク キャッシュ クリーニング スレッドの実行間隔。デフォルトは 120 秒です。 120 秒ごとに、対応するスレッドが EhCache 内のデータを消去します。
メモリストアエビクションポリシー いいえ メモリ キャッシュが最大サイズに達し、新しい要素が追加されると、キャッシュから要素を削除する戦略が使用されます。デフォルトは LRU (最も最近使用されていない) で、オプションは LFU (最も頻繁に使用されていない) と FIFO (先入れ先出し) です。

MyBatisのリバースエンジニアリング

  • フォワード エンジニアリング: まず Java エンティティ クラスを作成します。フレームワークはエンティティ クラスに基づいてデータベース テーブルを生成します。 Hibernate はフォワード エンジニアリングをサポートします
  • リバース エンジニアリング: 最初にデータベース テーブルを作成します。フレームワークは、データベース テーブルに基づいて次のリソースをリバース生成します。
    • Javaエンティティクラス
    • マッパーインターフェース
    • マッパーマッピングファイル

リバースエンジニアリングを作成する手順

依存関係とプラグインを追加する

<dependencies>
	<!-- MyBatis核心依赖包 -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.5.9</version>
	</dependency>
	<!-- junit测试 -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.13.2</version>
		<scope>test</scope>
	</dependency>
	<!-- MySQL驱动 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>8.0.27</version>
	</dependency>
	<!-- log4j日志 -->
	<dependency>
		<groupId>log4j</groupId>
		<artifactId>log4j</artifactId>
		<version>1.2.17</version>
	</dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
	<!-- 构建过程中用到的插件 -->
	<plugins>
		<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
		<plugin>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-maven-plugin</artifactId>
			<version>1.3.0</version>
			<!-- 插件的依赖 -->
			<dependencies>
				<!-- 逆向工程的核心依赖 -->
				<dependency>
					<groupId>org.mybatis.generator</groupId>
					<artifactId>mybatis-generator-core</artifactId>
					<version>1.3.2</version>
				</dependency>
				<!-- 数据库连接池 -->
				<dependency>
					<groupId>com.mchange</groupId>
					<artifactId>c3p0</artifactId>
					<version>0.9.2</version>
				</dependency>
				<!-- MySQL驱动 -->
				<dependency>
					<groupId>mysql</groupId>
					<artifactId>mysql-connector-java</artifactId>
					<version>8.0.27</version>
				</dependency>
			</dependencies>
		</plugin>
	</plugins>
</build>

MyBatisのコア設定ファイルを作成する

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"/>
    <typeAliases>
        <package name=""/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name=""/>
    </mappers>
</configuration>

リバースエンジニアリング用の設定ファイルを作成する

  • ファイル名は次のようにする必要があります。generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--
    targetRuntime: 执行生成的逆向工程的版本
    MyBatis3Simple: 生成基本的CRUD(清新简洁版)
    MyBatis3: 生成带条件的CRUD(奢华尊享版)
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3Simple">
        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root"
                        password="123456">
        </jdbcConnection>
        <!-- javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略 -->
        <sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"
                         targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!-- 逆向分析的表 -->
        <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="t_emp" domainObjectName="Emp"/>
        <table tableName="t_dept" domainObjectName="Dept"/>
    </context>
</generatorConfiguration>

MBGプラグインの生成ターゲットを実行します。

  • ここに画像の説明を挿入します

  • エラーが発生した場合:Exception getting JDBC Driver、pom.xml 内のデータベース ドライバーの構成が間違っている可能性があります

    • 依存関係にあるドライバー

    • ここに画像の説明を挿入します

    • mybatis-generator-maven-plugin プラグインのドライバー

    • ここに画像の説明を挿入します

    • 両方のドライバーのバージョンは同じである必要があります

  • の結果

  • ここに画像の説明を挿入します

QBC

お問い合わせ

  • selectByExample: 条件によってクエリを実行するには、サンプル オブジェクトまたは null を渡す必要があります。null を渡す場合は、条件がないこと、つまりすべてのデータがクエリされることを意味します。
  • example.createCriteria().xxx: 条件オブジェクトを作成し、andXXX メソッドを使用して SQL にクエリを追加します。各条件の間には and 関係があります。
  • example.or().xxx: または を使用して、以前に追加した条件を他の条件と結合します。
    ここに画像の説明を挿入します
@Test public void testMBG() throws IOException {
    
    
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	EmpExample example = new EmpExample();
	//名字为张三,且年龄大于等于20
	example.createCriteria().andEmpNameEqualTo("张三").andAgeGreaterThanOrEqualTo(20);
	//或者did不为空
	example.or().andDidIsNotNull();
	List<Emp> emps = mapper.selectByExample(example);
	emps.forEach(System.out::println);
}

ここに画像の説明を挿入します

追加と変更

  • updateByPrimaryKey: 主キーを使用してデータを変更します。特定の値が null の場合、対応するフィールドも null に変更されます。

  • updateByPrimaryKeySelective(): 主キーによる選択的なデータ変更。値が null の場合、このフィールドは変更されません。

ページネーションプラグイン

ページングプラグインを使用する手順

依存関係を追加する

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.2.0</version>
</dependency>

ページングプラグインの設定

  • MyBatis のコア構成ファイル (mybatis-config.xml) でプラグインを構成します。
  • ここに画像の説明を挿入します
<plugins>
	<!--设置分页插件-->
	<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

ページングプラグインの使用

ページングをオンにする

  • クエリ前関数を使用するPageHelper.startPage(int pageNum, int pageSize) ページング関数を有効にします
    • pageNum: 現在のページのページ番号
    • pageSize: 各ページに表示されるアイテムの数
@Test
public void testPageHelper() throws IOException {
    
    
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	//访问第一页,每页四条数据
	PageHelper.startPage(1,4);
	List<Emp> emps = mapper.selectByExample(null);
	emps.forEach(System.out::println);
}

ここに画像の説明を挿入します

ページネーション関連データ

方法 1: 直接出力
@Test
public void testPageHelper() throws IOException {
    
    
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	//访问第一页,每页四条数据
	Page<Object> page = PageHelper.startPage(1, 4);
	List<Emp> emps = mapper.selectByExample(null);
	//在查询到List集合后,打印分页数据
	System.out.println(page);
}
  • ページネーション関連データ:

    Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}]
    
方法 2 は PageInfo を使用します
  • クエリを実行してリスト コレクションを取得した後、PageInfo<T> pageInfo = new PageInfo<>(List<T> list, intnavigatePages) を使用してページング関連データを取得します
    • リスト: ページング後のデータ
    • navigatePages: ナビゲーション ページングのページ数
@Test
public void testPageHelper() throws IOException {
    
    
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
	PageHelper.startPage(1, 4);
	List<Emp> emps = mapper.selectByExample(null);
	PageInfo<Emp> page = new PageInfo<>(emps,5);
	System.out.println(page);
}
  • ページネーション関連データ:

    PageInfo{
    pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=8, pages=2, 
    list=Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=8, pages=2, reasonable=false, pageSizeZero=false}[Emp{eid=1, empName='admin', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=2, empName='admin2', age=22, sex='男', email='[email protected]', did=3}, Emp{eid=3, empName='王五', age=12, sex='女', email='[email protected]', did=3}, Emp{eid=4, empName='赵六', age=32, sex='男', email='[email protected]', did=1}], 
    prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}
    
  • リスト内のデータは、方法 1 で直接出力されたページ データと同等です。

一般的に使用されるデータ:
  • pageNum: 現在のページのページ番号
  • pageSize: 各ページに表示されるアイテムの数
  • サイズ: 現在のページに表示される実際のアイテム数
  • total: レコードの合計数
  • ページ: 総ページ数
  • prePage: 前のページのページ番号
  • nextPage: 次のページのページ番号
  • isFirstPage/isLastPage: 最初のページか最後のページか
  • hasPreviousPage/hasNextPage: 前ページ/次ページの有無
  • navigatePages: ナビゲーション ページングのページ数
  • navigatepageNums: ナビゲーション ページングのページ番号、[1,2,3,4,5]

おすすめ

転載: blog.csdn.net/Coastlise/article/details/134888202