目次
2.2. ラッパーパラメータの受け渡し + アノテーション SQL
1 はじめに
Mybatis-Plus (以下、MBP) の本来の目的は開発を簡素化することであり、開発者が自分で SQL ステートメントを記述することは推奨されませんが、顧客のニーズがより複雑で、要求された条件を達成することが困難な場合があります。 MBP が提供する Service、Mapper、および Wrapper の組み合わせを使用するだけで要件を満たします。; 次に、カスタム SQL を使用します。
Java 開発では、mybatis-plus を使用して SQL 操作を実行します。mybatis-plus は一般的に使用される多くのインターフェイスをカプセル化するため、mybatis に比べて時間と労力を節約できることがよくあります。ただし、より複雑なクエリの場合、mybatis-plus は比較すると見劣りするため、SQL ステートメントをカスタマイズする必要があります。この記事では、mybatis-plus/mybatisを利用する際のSQL文や動的SQLなどのカスタマイズ方法を紹介します。
Mybatis-Plus がカスタマイズを実装するには、いくつかの方法があります。
1) SQLに注釈を付ける
2) ラッパーパスパラメータ+アノテーションSQL
制限事項: 複数テーブルの関連付けクエリには適していません。クエリ フィールドとコードが多すぎると乱雑になります。
3) ラッパーパラメーターの受け渡し + XML ファイル SQL:推奨
4) オブジェクトパラメータの受け渡し + XMLファイルSQL
最も伝統的な書き方ですが、単純な単一テーブルのクエリではプロセスが煩雑で、設定も面倒です
2. SQL の特定の実装をカスタマイズする
2.1. SQLに注釈を付ける
Mybatis-plusでは、アノテーションによるSQL記述を実現するSQLアノテーション機能を提供していますが、SQLにアノテーションを付与するには、Mybatisの設定ファイルでアノテーション機能を有効にすることが前提となります。
Mapper の継承クラスで完全なカスタム SQL を使用できます。
//多数据源情况下,@DS注解用于指定数据源
@DS("zw-mysqldb")
public interface CarMapper extends BaseMapper<Car> {
@Select("select * from car where car_seq = #{carSeq}")
Car queryCar(String carSeq);
}
@RequestMapping("/ok")
public void testCustomSQL2() {
Car car = carMapper.queryCar("11");
System.out.println(car.toString());
}
補充:
1)使用@Param注解
当以下面的方式进行写SQL语句时:
@Select("select column from table where userid = #{userid} ")
public int selectColumn(int userid);
当你使用了使用@Param注解来声明参数时,如果使用 #{} 或 ${} 的方式都可以。
@Select("select column from table where userid = ${userid} ")
public int selectColumn(@Param("userid") int userid);
当你不使用@Param注解来声明参数时,必须使用使用 #{}方式。如果使用 ${} 的方式,会报错。
@Select("select column from table where userid = ${userid} ")
public int selectColumn(@Param("userid") int userid);
2)不使用@Param注解
不使用@Param注解时,参数只能有一个,并且是Javabean。在SQL语句里可以引用JavaBean的属性,而且只能引用JavaBean的属性。
// 这里id是user的属性
@Select("SELECT * from Table where id = ${id}")
Enchashment selectUserById(User user);
上記のコードでは、SQL アノテーションを付ける方法が使用されており、SQL ステートメントは @Select アノテーションによって指定されています。@Param アノテーションを使用してメソッド内でパラメータ名を指定すると、パラメータの転送が容易になります。パラメータ名は SQL パラメータ名と一致するため、省略できます。
SQL にアノテーションを付ける利点は、コードが簡潔で読みやすいことと、Wrapper や他のメソッドと組み合わせて複雑な SQL を構築できることです。
2.2. ラッパーパラメータの受け渡し + アノテーション SQL
Wrapper メソッドを使用するいくつかの使用シナリオ:
1) 動的クエリ: Wrapper を使用して、さまざまなクエリ条件に従って SQL ステートメントを動的に結合し、正確なクエリを実現します。
2) 複数テーブル結合クエリ:複数テーブル結合クエリの場合、Wrapper を使用して SQL ステートメントを簡単に結合し、複数テーブル結合クエリを実現します。
3) ページング クエリ:ページング クエリでは、Wrapper を使用すると SQL ステートメントを簡単に結合してページング機能を実現できます。
4) 条件付きクエリ: Wrapper を使用して、さまざまな条件に従って SQL ステートメントを動的に結合し、条件付きクエリを実現します。
5) ソートクエリ: Wrapper を使用して SQL ステートメントを簡単に結合し、ソート機能を実現します。
SQL を Wrapper と組み合わせて使用して複雑な SQL を構築する場合、通常は次の手順を完了する必要があります。
a) Wrapper オブジェクトを作成する
Wrapperオブジェクトを作成することで、SQLの構築や条件設定を便利に行うことができます。以下は、Wrapper オブジェクトを作成するためのサンプル コードです。
QueryWrapper<Entity> wrapper = new QueryWrapper<>();
b) クエリ条件を設定する
Wrapper オブジェクトのメソッド (eq、ne など) を使用してクエリ条件を設定でき、他のメソッドを使用して等しい、等しくないなどの条件を設定できます。クエリ条件を設定するサンプルコードは次のとおりです。
wrapper.eq("column1", value1)
.ne("column2", value2)
.like("column3", value3);
//示例
wrapper.eq("car_state", "1")
.like("car_id", "渝A");
c) ソート条件の設定(必須ではありません)
Wrapper オブジェクトの orderBy メソッドを使用して、orderByAsc、orderByDesc などの並べ替え条件を設定できます。また、他のメソッドでは、昇順、降順、その他の条件を設定できます。以下はソート条件を設定するサンプルコードです。
wrapper.orderByAsc("car_id")
d) ページネーション条件の設定 (必須ではありません)
Wrapper オブジェクトのメソッドを使用して、ページネーションの条件を設定できます。たとえば、page メソッドでは、ページ番号や各ページのサイズなどの条件を設定できます。ページネーション条件を設定するサンプルコードは次のとおりです。
Page<Car> resultPage = new Page<>(1, 10);
carMapper.selectByPrimaryKey(resultPage,wrapper)
e) マッパーインターフェイス
@Select("select * from car ${ew.customSqlSegment}")
Page<Car> selectByPrimaryKey(Page<Car> page, @Param(Constants.WRAPPER) QueryWrapper<Car> queryWrapper);
f) SQL 操作の実行
インターフェイスのメソッドは、selectList、selectPage などの SQL 操作を実行し、その他のメソッドは SQL クエリ操作を実行でき、クエリをカスタマイズすることもできます。以下は、SQL 操作を実行するための完全なコードのサンプルです。
//分页查询方式1
QueryWrapper<Car> wrapper = new QueryWrapper<>();
Page<Car> resultPage = new Page<>(1, 10);
wrapper.eq("car_state", "1")
.like("car_id", "渝A")
.orderByAsc("car_id");//排序
carMapper.selectByPrimaryKey(resultPage,wrapper);
//分页查询方式2
IPage<Car> page = new Page<>(1, 10); // 分页查询
LambdaQueryWrapper<Car> qw = new LambdaQueryWrapper<Car>()
.like(Car::getCarId, "渝A") // 车牌号 =
.eq(Car::getCarState, 1); // 状态
//selectPage是BaseMapper自带方法
IPage<Car> userPage = carMapper.selectPage(page, qw);
知らせ:
1) QueryWrapper でカスタム uservo クラスを使用します。LambdaQueryWrapper は使用できません
2) 上記の IPage と Page の両方をページングに使用できます。
XMLファイル
g) 実行結果:
補充:
実際のアプリケーションでは、LambdaQueryWrapper と QueryWrapper を使用して、さまざまなビジネス ニーズを満たすために、より複雑なクエリ操作を実装することもできます。たとえば、動的クエリには LambdaQueryWrapper と QueryWrapper を使用し、フロントエンドから渡されるパラメータを判断して SQL ステートメントを組み合わせることで、柔軟なクエリ操作を実現できます。
public List<UserEntity> getUserList(String name, Integer age) {
LambdaQueryWrapper<UserEntity> qw = new LambdaQueryWrapper<UserEntity>()
.eq(StringUtils.isNotEmpty(name), UserEntity::getName, name) // 姓名 = name
.gt(age != null, UserEntity::getAge, age); // 年龄 > age
return userMapper.selectList(qw);
}
上記のコードでは、LambdaQueryWrapper を通じて動的クエリ操作を実装しました。渡された name パラメータが空でない場合は、等しいクエリ条件が追加され、渡された age パラメータが空でない場合は、より大きいクエリ条件が追加されます。
このようなクエリ操作では、フロントエンドから渡されたパラメータに従って SQL ステートメントを柔軟に組み合わせて、より多くのビジネス ニーズを実現できます。
知らせ:
1)マッパー メソッドの @Param(Constants.WRAPPER) ラッパー クエリ オブジェクト。Constants.WRAPPER の値は新しいです。
2)まず ew.emptyOfWhere に where 条件があるかどうかを判断し、存在する場合はそれを結合します。3) ew.customSqlSegment の値は WHERE + sql ステートメントであり、WHERE 文字列を含まない別の ew.sqlSegment があります。
4) ${ew.customSqlSegment} は、Wapper クエリ条件を表すクエリ条件プレースホルダーです。
もちろん、Mybatis-Plus は、selectObjs、selectByMap など、直接使用できるいくつかのカスタム SQL メソッドを提供します。次に例を示します。
List<Object> objs = userMapper.selectObjs(
new QueryWrapper<User>().select("max(age)").eq("name", "张三")
);
2.3. ラッパーパスパラメータ+XMLファイルSQL
ラッパーパラメータの受け渡しはMybatisの高度な操作メソッドであり、クエリ時にパラメータを動的に渡すことができます。
1) マッパークラス
Car selectBySeq @Param(Constants.WRAPPER) QueryWrapper<Car> queryWrapper);
2) XML設定ファイル
<select id="selectBySeq " resultMap="BaseResultMap">
select * from `car` ${ew.customSqlSegment}
</select>
3) Wapper を介してクエリパラメータを渡す
Wrapper を使用してパラメータを動的に渡す
1. Wrapper 基本クラスを使用して、Where の背後にある SQL ステートメントをカスタマイズします。
2.QueryWrapperを使用する
-
選択 | select(文字列...sqlSelect)
例select("id", "name", "age")
上記 2 つの方法のいずれかを選択し、パラメータは Wrapper です。
@RequestMapping("/ok")
public void testCustomSQL2() {
LambdaQueryWrapper<Car> query = new LambdaQueryWrapper<>();
query.eq(Car::getCarId, "11");
Car car= carMapper.queryCarSeq(query);
System.out.println(car.toString());
}
//或者
Wrapper wrapper = new QueryWrapper<Car>().eq("car_state", 1).like("cai_id", "渝");
List<Car> userList = carMapper.queryCarSeq(wrapper);
XML ファイル SQL と Wrapper パラメータを組み合わせる利点は、コードの保守性、可読性、セキュリティが向上することです。コード量が多く、複数人での共同開発が必要なシナリオに適しており、SQL の実行を防ぐことができます。注射攻撃。
2.4. 通常のパラメータ渡し + XMLファイルSQL
リソース ディレクトリにマッパー フォルダーを作成し、UserMapper.xml などのマッパー インターフェイスと同じ名前の XML ファイルを作成して、カスタム SQL ステートメントを定義します。
//xml文件式,myabtis原生方式
Car selectByAnnotationXML(String seq);
マッパーの下にファイル UserDao.xml を作成します
<select id="selectByAnnotationXML" parameterType="java.lang.String" resultMap="BaseResultMap">
select *
from car
where car_seq = #{seq,jdbcType=VARCHAR}
</select>
この方法は、mybatis に連絡するときの最も基本的な方法です。
3. まとめ
一般に、SQL を記述する方法は 2 つあり、1 つはアノテーションを使用してマッパー メソッドに直接記述する方法、もう 1 つは XML ファイルに記述する方法です。パラメータを渡す方法も 2 つあり、1 つはパラメータを直接渡す方法です。 XML ファイルで SQL をアセンブルします。1 つは、Wapper を介してパラメーター条件付きコンストラクターを渡すことです。
アノテーションの利点
簡潔で理解しやすい: XML 構成と比較して、アノテーションの使用はより簡潔かつ直感的であり、コードがより読みやすく、保守しやすくなります。
デバッグが簡単:アノテーション構成を Java クラスに直接記述することができるため、XML 内の SQL を検索して変更する時間を短縮できます。
パフォーマンスの向上: 多数の CRUD 操作を実行する場合、XML 解析のオーバーヘッドがないため、アノテーション構成のパフォーマンスが向上します。
アノテーションのデメリット
メンテナンスが困難: SQL と Java コードを結合すると、特により複雑な SQL が含まれる場合、コードのメンテナンスとリファクタリングが困難になります。
SQL の可読性の低さ: XML で SQL を記述する場合と比較して、アノテーション内の SQL ステートメントは通常、より冗長で読みにくくなります。
XML の利点
保守が容易: SQL が Java コードから分離されているため、特に SQL を変更する必要がある場合、コードの保守が容易になります。
SQL の可読性の向上: SQL を XML で記述すると、SQL の形式がより明確になり、読みやすくなります。
管理が簡単: XML 構成ファイルはグローバルに管理できるため、プロジェクトの構造がより明確になります。
XML の欠点
複雑:注釈と比較して、XML 構成はより複雑で、より多くのコードが必要になります。
パフォーマンスの問題:多数の操作を実行すると、XML の解析と読み取りに一定の時間がかかり、システムのパフォーマンスが低下します。
つまり、アノテーションと XML の選択は、プロジェクトの実際の状況とニーズに応じて決定する必要があります。単純なクエリと操作にはアノテーションが適しており、複雑なクエリと操作には XML が適しています。