ホームページ  >  記事  >  データベース  >  MySQL の動的 SQL スプライシングについて話しましょう

MySQL の動的 SQL スプライシングについて話しましょう

WBOY
WBOY転載
2022-12-01 17:20:351965ブラウズ

この記事では、mysql に関する関連知識を提供します。主に動的 SQL スプライシングに関する関連コンテンツを紹介します。実際のビジネス開発では、通常、SQL ステートメントは動的にスプライシングされます。条件検索機能など、皆さんの参考になれば幸いです、一緒に見ていきましょう。

MySQL の動的 SQL スプライシングについて話しましょう

推奨学習: mysql ビデオ チュートリアル

1. 動的 SQL スプライシング

#目標

#mybatis タグを使用して動的 SQL スプライシングを実装できるようにする

#分析前の学習プロセスでは、使用した SQL ステートメントは非常に単純でした。実際のビジネス開発では、条件検索関数の SQL ステートメントなど、SQL ステートメントは動的に接続されることが多いです。
# 提供了一个功能:用户可以在页面上根据username、sex、address进行搜索
# 用户输入的搜索条件:可以是一个条件,也可能是两个、三个

# 只输入一个条件:姓名是"王"
SELECT * FROM USER WHERE username LIKE '%王%'
# 只输入一个条件:性别是“男”
SELECT * FROM USER WHERE sex = '男'
# 输入两个条件:姓名“王”,性别“男”
SELECT * FROM USER WHERE username LIKE '%王%' AND sex = '男'
# 输入三个条件:姓名“王”,性别“男”,地址“北京”
SELECT * FROM USER WHERE username LIKE '%王%' AND sex = '男' AND address LIKE '%北京%';

Mybatis では、SQL ステートメントはマッピング構成の XML ファイルに記述されます。 Mybatis は、動的 SQL スプライシングを実装するための XML タグをいくつか提供しています。

一般的に使用されるタグは次のとおりです:

##

: 判定に使用され、Java の if 判定に相当します
  • <where></where>: 通常、SQL ステートメント #<where></where>
  • where 1=1## を置き換えるために if と組み合わせて使用​​されます。 foreach></foreach>: コレクションを走査し、コレクションの内容を SQL ステートメントに結合するために使用されます。たとえば、スプライシング:
  • in (value1, value2, ...)
  • <sql></sql>: 再利用する SQL フラグメントを定義するために使用されます。目的
説明

1. Mybatis 環境の準備

Java プロジェクトの作成、jar パッケージのインポート、JavaBean の準備

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

  • マッピング構成の作成ファイル UserDao.xml

  • グローバル構成ファイルの作成 SqlMapConfig.xml

  • ログ構成ファイルの作成 log4j.properties

  • #2.

タグ: 文法紹介
<if test="判断条件,使用OGNL表达式进行判断">
	SQL语句内容, 如果判断为true,这里的SQL语句就会进行拼接</if>

使用例
ユーザーの名前と性別からユーザー情報を検索します。 User オブジェクトに検索条件を入力し、SQL ステートメントに渡します。
  • マッパー インターフェイスにメソッドを追加します。UserDao

package com.demo.dao;import com.demo.domain.User;import java.util.List;public interface UserDao {
    /**
     * 根据username和sex搜索用户
     * @param user 封装了搜索条件的User对象
     * @return 搜索的结果
     */
    List<User> search1(User user);}
  • マッピング ファイル UserDao.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.dao.UserDao">
      
          <!--
          if标签:用于条件判断
              语法:<if test="用OGNL表达式判断"> 如果判断为true,这里的内容会拼接上去 </if>
              注意:标签里写OGNL表达式,不要再加#{}、${}
              常用的OGNL表达式:
                  比较:>, <, >=, <=, ==, != 或者 gt, lt, gte, lte, eq, neq
                  逻辑:&&,||,! 或者 and, or, not
                  调用方法:username.length(),  list.size()
          -->
          <select id="search1" resultType="User">
              select * from user where 1=1        <if test="username != null and username.length()>0">
                  and username like "%"#{username}"%"        </if>
              <if test="sex != null and sex.length()>0">
                  and sex = #{sex}        </if>
          </select></mapper>
    • でステートメントを設定します。機能テスト、テスト クラスにテスト メソッドを追加します
      package com.demo;import com.demo.dao.UserDao;import com.demo.domain.User;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.io.InputStream;import java.util.List;public class SqlTest {
      
          private UserDao userDao;
          private SqlSession session;
          private InputStream is;
      
          /**
           * 要求:根据username和sex搜索用户
           *      搜索条件放到user对象里
           */
          @Test
          public void testSearch(){
              User user = new User();
              // user.setUsername("王");
              // user.setSex("男");
      
              List<User> userList = userDao.search1(user);
              userList.forEach(System.out::println);
          }
      
      
          @Before
          public void init() throws IOException {
              //1. 读取全局配置文件
              is = Resources.getResourceAsStream("SqlMapConfig.xml");
              //2. 得到一个SqlSession对象
              SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
              session = factory.openSession();
              userDao = session.getMapper(UserDao.class);
          }
      
          @After
          public void destroy() throws IOException {
              session.close();
              is.close();
          }}
    • 3.

      タグ文法の紹介

      先ほど練習した SQL ステートメントでは、where 1=1 と書きました。これを記述しないと、SQL 文に構文エラーが発生します。 Mybatis は、where 1=1
      :

      <where></where> タグを置き換えるテクノロジーを提供します。 コード例

      前の章の実装コードを最適化し、代わりに
      <where></where> タグを使用しますここで 1=1

      マッパー UserDao の search1 メソッド: 既存なので変更する必要はありません

        /**
         * 根据username和sex搜索用户
         * @param user 封装了搜索条件的User对象
         * @return 搜索的结果
         */List<User> search1(User user);
      • マッピング ファイル UserDao.xml
        • <!--
              where标签:让Mybatis帮我们生成一个where关键字
                  Mybatis会智能判断:
                      如果一个条件都没有,就不生成where关键字
                      如果有条件,会判断是否有多余的and关键字,把多余的and去掉
                  注意:建议把所有的where条件都放到where标签里边
              --><select id="search1" resultType="User">
              select * from user    <where>
                  <if test="username != null and username.length()>0">
                      and username like "%"#{username}"%"        </if>
                  <if test="sex != null and sex.length()>0">
                      and sex = #{sex}        </if>
              </where></select>
        • の SQL ステートメントを変更します。テスト クラスで機能テストを実行します。テスト メソッドを変更する必要はありません
          • @Testpublic void testSearch(){
                User user = new User();
                // user.setUsername("王");
                // user.setSex("男");
            
                List<User> userList = userDao.search1(user);
                userList.forEach(System.out::println);}
          • 4.
          • tag

            構文の紹介

            foreach タグ。通常、コレクションをループし、コレクションの内容を SQL ステートメントに結合するために使用されます。たとえば、複数の ID に基づいてユーザー情報をクエリする必要がある場合、その SQL ステートメントは次のとおりです:
            select * from user where id = 1 or id = 2 or id = 3;select * from user where id in (1, 2, 3);
            ID のコレクションを渡す場合、コレクションをどのように調べて、マッピング ファイル内の SQL ステートメントを結合すればよいでしょうか?これは、foreach
            タグを使用して実現できます。

            <!--
            foreach标签:
            	属性:
            		collection:被循环遍历的对象,使用OGNL表达式获取,注意不要加#{}
            		open:循环之前,拼接的SQL语句的开始部分
            		item:定义变量名,代表被循环遍历中每个元素,生成的变量名
            		separator:分隔符
            		close:循环之后,拼接SQL语句的结束部分
            	标签体:
            		使用#{OGNL}表达式,获取到被循环遍历对象中的每个元素
            --><foreach collection="" open="id in(" item="id" separator="," close=")">
                #{id}</foreach>

            使用例

            検索条件クラスQueryVOは以下のとおりです。
              package com.itheima.domain;public class QueryVO {
                  private Integer[] ids;
              
                  public Integer[] getIds() {
                      return ids;
                  }
              
                  public void setIds(Integer[] ids) {
                      this.ids = ids;
                  }}
            • マッパーにメソッドを追加 UserDao
              • /**
                     * QueryVO里有一个Integer[] ids
                     * 要求:根据ids查询对应的用户列表
                     */List<User> search2(QueryVO vo);
              • マッピング ファイル UserDao.xml
                •     <!--
                      foreach标签:用于循环遍历
                          collection:被循环的集合/数组
                          item:定义一个变量
                          separator:定义拼接时的分隔符
                          open:拼接字符串时的开始部分
                          close:拼接字符串时的结束部分
                  
                          相当于 for(Integer id: ids){}
                          select * from user where id in(41, 42, 45)
                      -->
                      <select id="search2" resultType="User">
                          <!--select * from user where id in(41, 42, 45)-->
                          select * from user where        <foreach collection="ids" open="id in(" item="id" separator="," close=")">
                              #{id}        </foreach>
                      </select>
                • にステートメントを設定します

                  Functional Test
                  •     @Test
                        public void testSearch2(){
                            QueryVO vo = new QueryVO();
                            vo.setIds(new Integer[]{41,42,43,44,45});
                            List<User> userList = userDao.search2(vo);
                            userList.forEach(System.out::println);
                        }
                  • 5.
                  • Tag

                    マッピング ファイル内select * from user など、繰り返される SQL フラグメントが多数あることがわかりました。 Mybatis は、繰り返される SQL フラグメントを抽出して再利用できる

                    タグを提供します。

                    语法介绍

                    在映射文件中定义SQL片段:

                    <sql id="唯一标识">sql语句片段</sql>

                    在映射文件中引用SQL片段:

                    <include refid="sql片段的id"></include>
                    使用示例

                    在查询用户的SQL中,需要重复编写:select * from user。把这部分SQL提取成SQL片段以重复使用

                    • 要求:QueryVO里有ids,user对象。根据条件进行搜索
                    • 修改QueryVO,增加成员变量user

                    package com.itheima.domain;/**
                     * @author liuyp
                     * @date 2021/09/07
                     */public class QueryVO {
                        private Integer[] ids;
                        private User user;
                    
                        //get/set方法……}
                    • 在映射器UserDao里加方法

                        /**
                         * 动态SQL拼接的综合应用:if、where、foreach
                         * 要求:QueryVo里有ids、username、sex值,根据这些值进行搜索
                         */
                        List<User> search3(QueryVO vo);
                    • 在映射文件UserDao.xml里配置statement

                    <select id="search3" resultType="User">
                        <!--select * from user-->
                        <include refid="selUser"/>
                        <where>
                            <if test="ids != null and ids.length > 0">
                                <foreach collection="ids" open="and id in(" item="id" separator="," close=")">
                                    #{id}            </foreach>
                            </if>
                            <!--<if test="user != null">
                                    <if test="user.username != null and user.username.length() > 0">
                                        and username like "%"#{user.username}"%"
                                    </if>
                                    <if test="user.sex != null and user.sex.length() > 0">
                                        and sex = #{user.sex}
                                    </if>
                                </if>-->
                            <include refid="userCondition"/>
                        </where></select><!--
                        sql标签:用于定义一个sql片段
                        include标签:什么时候要引用某个SQL片段,就使用include标签
                        注意:引入SQL片段之后,最终的SQL语句必须要完全符合语法
                        --><sql id="selUser">select * from user</sql><sql id="userCondition">
                        <if test="user != null">
                            <if test="user.username != null and user.username.length() > 0">
                                and username like "%"#{user.username}"%"        </if>
                            <if test="user.sex != null and user.sex.length() > 0">
                                and sex = #{user.sex}        </if>
                        </if></sql>
                    • 在测试类里加测试方法

                        @Test
                        public void testSearch3(){
                            QueryVO vo = new QueryVO();
                            vo.setIds(new Integer[]{41,42,43,44,45});
                    
                            // User user = new User();
                            // user.setUsername("王");
                            // user.setSex("男");
                            // vo.setUser(user);
                    
                            List<User> userList = userDao.search3(vo);
                            userList.forEach(System.out::println);
                        }

                    推荐学习:mysql视频教程

                    以上がMySQL の動的 SQL スプライシングについて話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

                    声明:
                    この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。