日常の開発では、単一テーブルの CRUD 関数コードは反復性が高く、難しくないことがわかるはずです。コードのこの部分は比較的大きく、開発に時間がかかることがよくあります。
したがって、現在企業では、単一テーブルの CRUD 開発作業を簡素化または省略するために、いくつかのコンポーネントが使用されています。現在中国でよく使用されているコンポーネントの 1 つは MybatisPlus です。
公式サイトは以下の通りです。
もちろん、MybatisPlus は単一テーブルの操作を簡素化するだけでなく、Mybatis の機能に対する多くの機能強化も行っています。これにより、開発がよりシンプルかつ効率的になります。
今日の学習を通じて、私たちは次の目標を達成します。
-
MybatisPlus を使用して基本的な CRUD を実装できる
-
条件付き構築を使用してクエリを構築し、ステートメントを更新します
-
MybatisPlus で共通のアノテーションを使用します
-
MybatisPlus を使用して列挙型フィールドと JSON 型フィールドを処理します
-
MybatisPlus を使用してページングを実装します
テストを容易にするために、まず新しいプロジェクトを作成し、いくつかの基本データを準備します。
1.環境の準備
プレコース教材で提供されているプロジェクトをワークスペースにコピーします (スペースや特殊文字は含めないでください)。
次に、IDEA ツールで開きます。プロジェクトの構造は次のとおりです。
プロジェクトの JDK バージョンを JDK11 に設定することに注意してください。まず、プロジェクト構造設定をクリックします。
ポップアップ ウィンドウで JDK を設定します。
次に、2 つのテーブルをインポートする必要があります。SQL ファイルは授業前の資料で提供されています。
対応するデータベース テーブル構造は次のとおりです。
最後に、application.yaml
jdbc パラメータを独自のデータベース パラメータに変更します。
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: MySQL123
logging:
level:
com.itheima: debug
pattern:
dateformat: HH:mm:ss
2. クイックスタート
たとえば、User テーブルに CRUD を実装する場合、必要な手順は次のとおりです。
-
MybatisPlus 依存関係を導入する
-
マッパーの定義
2.1依存関係を導入する
MybatisPlus は、自動 Mybatis と MybatisPlus の自動組み立て機能を実現するためのスターターを提供します。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
このスターターには mybatis の自動アセンブリが含まれているため、Mybatis スターターを完全に置き換えることができます。最終的に、プロジェクトの依存関係は次のようになります。
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.2 マッパーの定義
単一テーブル CRUD を簡素化するために、MybatisPlus は、BaseMapper
既に単一テーブル CRUD を実装した基本インターフェイスを提供します。
したがって、カスタム マッパーが this を実装している限りBaseMapper
、単一テーブル CRUD を独自に実装する必要はありません。com.itheima.mp.mapper
mp-demo のパッケージの下にあるインターフェイスを変更しUserMapper
、継承させますBaseMapper
。
コードは以下のように表示されます。
package com.itheima.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
public interface UserMapper extends BaseMapper<User> {
}
2.3 テスト
新しいテスト クラスを作成し、いくつかの単体テストを作成し、基本的な CRUD 関数をテストします。
package com.itheima.mp.mapper;
import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import java.util.List;
@SpringBootTest
class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
void testInsert() {
User user = new User();
user.setId(5L);
user.setUsername("Lucy");
user.setPassword("123");
user.setPhone("18688990011");
user.setBalance(200);
user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userMapper.insert(user);
}
@Test
void testSelectById() {
User user = userMapper.selectById(5L);
System.out.println("user = " + user);
}
@Test
void testSelectByIds() {
List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L, 5L));
users.forEach(System.out::println);
}
@Test
void testUpdateById() {
User user = new User();
user.setId(5L);
user.setBalance(20000);
userMapper.updateById(user);
}
@Test
void testDelete() {
userMapper.deleteById(5L);
}
}
ご覧のとおり、実行プロセス中に出力される SQL ログは非常に標準的なものです。
11:05:01 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
11:05:02 INFO 15524 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Preparing: SELECT id,username,password,phone,info,status,balance,create_time,update_time FROM user WHERE id=?
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : ==> Parameters: 5(Long)
11:05:02 DEBUG 15524 --- [ main] c.i.mp.mapper.UserMapper.selectById : <== Total: 1
user = User(id=5, username=Lucy, password=123, phone=18688990011, info={"age": 21}, status=1, balance=20000, createTime=Fri Jun 30 11:02:30 CST 2023, updateTime=Fri Jun 30 11:02:30 CST 2023)
3. 共通の注釈
先ほどの導入ケースでは、依存関係を導入し、MybatisPlus を使用できるように BaseMapper を継承するだけでしたが、これは非常に単純です。しかし、ここで疑問が生じます。MybatisPlus はどのテーブルをクエリしたいのかをどのようにして知るのでしょうか? テーブルにはどのようなフィールドがありますか?
UserMapper が BaseMapper を継承するときにジェネリックを指定したことを思い出してください。
ジェネリック タイプの User は、データベースに対応する PO です。
MybatisPlus は、PO エンティティ情報に基づいてテーブル情報を推測し、SQL を生成します。デフォルトでは:
-
MybatisPlus は、PO エンティティのクラス名をキャメルケースに変換し、テーブル名として下線を付けます。
-
MybatisPlus は、PO エンティティのすべての変数名をキャメル ケースに変換し、テーブルのフィールド名として下線を引き、変数タイプに基づいてフィールド タイプを推測します。
-
MybatisPlus は、id という名前のフィールドを主キーとして使用します。
ただし、多くの場合、デフォルトの実装は実際のシナリオと一致しないため、MybatisPlus はテーブル情報の宣言を容易にするためにいくつかの注釈を提供します。
3.1@テーブル名
例証します:
-
説明: テーブル名のアノテーション。エンティティ クラスに対応するテーブルを識別します。
-
使用する場所: エンティティクラス
例:
@TableName("user")
public class User {
private Long id;
private String name;
}
TableName アノテーションでは、テーブル名の指定に加えて、他の多くの属性も指定できます。
属性 |
タイプ |
必ず指定してください |
デフォルト値 |
説明する |
価値 |
弦 |
いいえ |
「」 |
テーブル名 |
スキーマ |
弦 |
いいえ |
「」 |
スキーマ |
グローバルプレフィックスを保持する |
ブール値 |
いいえ |
間違い |
グローバル tablePrefix 値を使用し続けるかどうか (グローバル tablePrefix が有効な場合) |
結果マップ |
弦 |
いいえ |
「」 |
XML 内の resultMap の ID (特定の種類のエンティティ クラス オブジェクト バインディングを満たすために使用されます) |
autoResultMap |
ブール値 |
いいえ |
間違い |
resultMapを自動構築して使用するかどうか(resultMapが設定されている場合、resultMapの自動構築と注入は行われません) |
除外プロパティ |
弦[] |
いいえ |
{} |
除外する必要がある属性名@3.3.1 以降 |
3.2@テーブルID
例証します:
-
説明: 主キー アノテーション。エンティティ クラスの主キー フィールドを識別します。
-
使用場所: エンティティ クラスの主キー フィールド
例:
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
}
TableId
注釈は 2 つのプロパティをサポートします。
属性 |
タイプ |
必ず指定してください |
デフォルト値 |
説明する |
---|---|---|---|---|
価値 |
弦 |
いいえ |
「」 |
テーブル名 |
タイプ |
列挙型 |
いいえ |
IdType.NONE |
主キーのタイプを指定する |
IdType
サポートされているタイプは次のとおりです。
価値 |
説明する |
---|---|
オート |
データベースIDの自動インクリメント |
なし |
ステートレス。この型には主キー セットがありません (注釈はグローバルに続くことに相当し、グローバル Rio は INPUT にほぼ等しい)。 |
入力 |
挿入する前に主キーの値を設定します |
ASSIGN_ID |
ID を割り当てます (主キーのタイプは数値 (Long および Integer) または String) (3.3.0 以降)、インターフェイス IdentifierGenerator のメソッド nextId を使用します (デフォルトの実装クラスは DefaultIdentifierGenerator スノーフレーク アルゴリズムです)。 |
ASSIGN_UUID |
UUID を割り当てます。主キーのタイプは String (3.3.0 以降)、インターフェイス IdentifierGenerator のメソッド nextUUID を使用します (デフォルトのメソッド)。 |
|
分散グローバルユニークID長整数型(ASSIGN_IDを使用してください) |
|
32 ビット UUID 文字列 (ASSIGN_UUID を使用してください) |
|
分散グローバルユニーク ID 文字列型 (ASSIGN_ID を使用してください) |
ここには一般的なものが 3 つあります。
-
AUTO
: データベース ID を使用して自動的に拡張します -
INPUT
: IDを手動で生成します -
ASSIGN_ID
: スノーフレーク アルゴリズムは、Long
タイプに対してグローバルに一意の ID を生成します。これがデフォルトの ID 戦略です。
3.3@テーブルフィールド
例証します:
説明: 共通フィールドの注釈
例:
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private Integer age;
@TableField("isMarried")
private Boolean isMarried;
@TableField("concat")
private String concat;
}
@TableField
通常、いくつかの特別な状況を除いて、フィールドに注釈を追加する必要はありません。
-
メンバー変数名がデータベースフィールド名と一致しません
-
メンバー変数
isXXX
には という名前が付けられており、JavaBean
仕様上MybatisPlus
フィールドを識別する際に削除されるためis
、データベースとの不整合が発生します。 -
メンバー変数名はデータベースと一致していますが、データベースのキーワードと競合しています。アノテーションを使用して
@TableField
フィールド名に ```` エスケープを追加する
サポートされているその他の属性は次のとおりです。
属性 |
タイプ |
必須 |
デフォルト値 |
説明する |
価値 |
弦 |
いいえ |
「」 |
データベースフィールド名 |
存在する |
ブール値 |
いいえ |
真実 |
データベーステーブルのフィールドかどうか |
状態 |
弦 |
いいえ |
「」 |
エンティティ クエリの比較条件を指定するフィールドです。値が設定されている場合は、設定された値が優先されます。そうでない場合は、デフォルトのグローバル %s=#{%s} が使用されます。 (新しいウィンドウが開きます)を参照してください。 |
アップデート |
弦 |
いいえ |
「」 |
フィールド更新セットは部分的に挿入されます。例: version フィールドに update="%s+1" という注釈を付けた場合、更新時に version=version+1 が設定されることを示します (この属性は el 属性よりも高い優先順位を持ちます) |
挿入戦略 |
列挙型 |
いいえ |
フィールド戦略.DEFAULT |
例:NOT_NULL table_a(<if test="columnProperty != null">column</if>) の値 (<if test="columnProperty != null">#{columnProperty}</if>) に挿入します。 |
更新戦略 |
列挙型 |
いいえ |
フィールド戦略.DEFAULT |
例:IGNORED update table_a set column=#{columnProperty} |
どこ戦略 |
列挙型 |
いいえ |
フィールド戦略.DEFAULT |
例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
埋める |
列挙型 |
いいえ |
フィールドフィル.DEFAULT |
フィールド自動入力戦略 |
選択する |
ブール値 |
いいえ |
真実 |
選択クエリを実行するかどうか |
グローバルフォーマットを維持する |
ブール値 |
いいえ |
間違い |
処理にグローバル形式を使用し続けるかどうか |
jdbcタイプ |
Jdbcタイプ |
いいえ |
JdbcType.UNDEFINED |
JDBC タイプ (このデフォルト値は、この値に従って有効になることを意味するものではありません) |
タイプハンドラー |
タイプハンドラー |
いいえ |
タイププロセッサ (このデフォルト値は、この値に従って有効になることを意味するものではありません) |
|
数値スケール |
弦 |
いいえ |
「」 |
小数点以下を保持する桁数を指定します |
4. 共通構成
MybatisPlus は、yaml ファイルに基づくカスタム構成もサポートしています。詳細については、公式ドキュメントを参照してください。
ほとんどの構成にはデフォルト値があるため、それらを構成する必要はありません。ただし、次のようにデフォルト値がないものもあります。
-
エンティティクラスのエイリアススキャンパッケージ
-
グローバルIDタイプ
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po
global-config:
db-config:
id-type: auto # 全局id类型为自增长
MyBatisPlus は手書き SQL もサポートしており、マッパー ファイルの読み取りアドレスは自分で設定できることに注意してください。
mybatis-plus:
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,当前这个是默认值。
デフォルト値が であることがわかりますclasspath*:/mapper/**/*.xml
。これは、mapper.xml ファイルをこのディレクトリに配置する限り、このファイルがロードされることを意味します。
たとえば、新しいUserMapper.xml
ファイルを作成してみましょう。
次に、その中にメソッドを定義します。
<?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.itheima.mp.mapper.UserMapper">
<select id="queryById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
次に、UserMapperTest
テスト クラスでメソッドをテストします。
@Test
void testQuery() {
User user = userMapper.queryById(1L);
System.out.println("user = " + user);
}