The role of Mybatis dynamic Sql

Table of contents

1. mybatis dynamic SQL

 1、if

2、foreach

 3、choose、when、otherwise

 2. mybatis fuzzy query

 1. Three ways of fuzzy query in mybatis

 2. The difference between # and $ in mybatis

1, pagination

1. Introduction to PageHelper

Advantages of PageHelper plugin:

2. Use of PageHelper

 1. Import pom dependencies

2. Mybatis.cfg.xml configures the interceptor

mock test

 3. Special character processing

 1. Use escape characters

2. Use CDATA sections


1. mybatis dynamic SQL

update 表名 set name=?,age=? where id=?

If our front desk does not pass in parameters, for example, if our name value is not passed in, the name field value will be changed to null, which violates the original intention of our coding.

Many people will use something like where 1 = 1 as a prefix. In the code, they will use if to determine whether it is null , and then use and to perform a SQL splicing.

We can use several commonly used tags:

 1、if

In the if tag, if the conditions in test are met, the following sql statements will be spliced.

<!-- 示例 -->
<select id="updateByPrimaryKeySelective" parameterType="com.xzs.model.Book">
        SELECT * FROM Book WHERE price>= 9.9
        <if test="name != null and name != ''">
            AND name like '%${name}%'
        </if>
</select>

2、foreach

When we call the delete method, we usually use it in conjunction with the IN query condition in the SQL statement.

delete from student where id in()


The parameterType is List (linked list) or Array (array). When referenced later, the parameter name must be list or array. For example, in the foreach tag, the collection attribute is the collection that needs to be iterated. Since the input parameter is a List, the parameter name must be list.

<select id="selectById" resultType="com.xzs.model.Book" parameterType="java.util.List" >
      select
      <include refid="Base_Column_List"/>
      from t_mvc_book
      where bid in
      <foreach collection="bids" item="bid" open="(" separator="," close=")">
          #{bid}
      </foreach>
  </select>

Test the result

 

 

 3、choose、when、otherwise

You can use choose , when and otherwise elements to implement logic similar to switch statements

<select id="getUser" parameterType="int" resultType="User">
  SELECT * FROM users
  WHERE 1=1
  <choose>
    <when test="id != null">
      AND id = #{id}
    </when>
    <when test="name != null">
      AND name = #{name}
    </when>
    <otherwise>
      AND status = 'ACTIVE'
    </otherwise>
  </choose>
</select>

 If the id passed in is not empty, this condition will be included in the SQL statement AND id = #{id}; if the name passed in is not empty, this condition will be included in the SQL statement AND name = #{name}; otherwise, this condition will be included in the SQL statement AND status = 'active'.

 2. mybatis fuzzy query

We write an xml file, log4j2.xml is used to print out your sql statement

<?xml version="1.0" encoding="UTF-8"?>
 
<!-- status : 指定log4j本身的打印日志的级别.ALL< Trace < DEBUG < INFO < WARN < ERROR
	< FATAL < OFF。 monitorInterval : 用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s. -->
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <!-- 配置日志文件输出目录 ${sys:user.home} -->
        <Property name="LOG_HOME">/root/workspace/lucenedemo/logs</Property>
        <property name="ERROR_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/error</property>
        <property name="WARN_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/warn</property>
        <property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} - %msg%n</property>
    </Properties>
 
    <Appenders>
        <!--这个输出控制台的配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="trace" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <!-- 输出日志的格式 -->
            <!-- %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间 %p : 日志输出格式 %c : logger的名称
                %m : 日志内容,即 logger.info("message") %n : 换行符 %C : Java类名 %L : 日志输出所在行数 %M
                : 日志输出所在方法名 hostName : 本地机器名 hostAddress : 本地ip地址 -->
            <PatternLayout pattern="${PATTERN}" />
        </Console>
 
        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
        <!--append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
        <File name="log" fileName="logs/test.log" append="false">
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </File>
        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size, 则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
        <RollingFile name="RollingFileInfo" fileName="${LOG_HOME}/info.log"
                     filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="info" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <!-- 基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。 modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am. -->
                <!-- 关键点在于 filePattern后的日期格式,以及TimeBasedTriggeringPolicy的interval, 日期格式精确到哪一位,interval也精确到哪一个单位 -->
                <!-- log4j2的按天分日志文件 : info-%d{yyyy-MM-dd}-%i.log -->
                <TimeBasedTriggeringPolicy interval="1"
                                           modulate="true" />
                <!-- SizeBasedTriggeringPolicy:Policies子节点, 基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小. -->
                <!-- <SizeBasedTriggeringPolicy size="2 kB" /> -->
            </Policies>
        </RollingFile>
 
        <RollingFile name="RollingFileWarn" fileName="${WARN_LOG_FILE_NAME}/warn.log"
                     filePattern="${WARN_LOG_FILE_NAME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="2 kB" />
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20" />
        </RollingFile>
 
        <RollingFile name="RollingFileError" fileName="${ERROR_LOG_FILE_NAME}/error.log"
                     filePattern="${ERROR_LOG_FILE_NAME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT"
                             onMismatch="DENY" />
            <PatternLayout
                    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
            <Policies>
                <!-- log4j2的按分钟 分日志文件 : warn-%d{yyyy-MM-dd-HH-mm}-%i.log -->
                <TimeBasedTriggeringPolicy interval="1"
                                           modulate="true" />
                <!-- <SizeBasedTriggeringPolicy size="10 MB" /> -->
            </Policies>
        </RollingFile>
 
    </Appenders>
 
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
    <Loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息 -->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>
 
        <!-- 第三方日志系统 -->
        <logger name="org.springframework" level="ERROR" />
        <logger name="org.hibernate" level="ERROR" />
        <logger name="org.apache.struts2" level="ERROR" />
        <logger name="com.opensymphony.xwork2" level="ERROR" />
        <logger name="org.jboss" level="ERROR" />
 
 
        <!-- 配置日志的根节点 -->
        <root level="all">
            <appender-ref ref="Console" />
            <appender-ref ref="RollingFileInfo" />
            <appender-ref ref="RollingFileWarn" />
            <appender-ref ref="RollingFileError" />
        </root>
 
    </Loggers>
 
</Configuration>

 

 1. Three ways of fuzzy query in mybatis

1.The first type

<select id="like01" resultType="com.xzs.model.Book" parameterType="java.util.List">
        select
        <include refid="Base_Column_List"/>
        from t_mvc_book
        where bname like #{bname}
    </select>

Test results

 @Test
    public void like01() {
        bookbiz.like01("%圣%").forEach(System.out::println);
    }

 

 The second type: $ requires single quotes, and the parameters passed in $ are in the form of placeholders.

 <select id="like02" resultType="com.xzs.model.Book" parameterType="java.util.List">
        select
        <include refid="Base_Column_List"/>
        from t_mvc_book
        where bname like '${bname}'
    </select>

 Test results

  @Test
    public void like02() {
        bookbiz.like02("%圣%").forEach(System.out::println);
    }

 

 The third kind

<select id="like03" resultType="com.xzs.model.Book" parameterType="java.util.List">
        select
        <include refid="Base_Column_List"/>
        from t_mvc_book
        where bname like concat('%',#{bname},'%')
    </select>

Test results

    @Test
    public void like03() {
        bookbiz.like03("%圣%").forEach(System.out::println);
    }

 

 2. The difference between # and $ in mybatis

  1. $ is a placeholder assignment, # is preprocessing SQL.
  2. In the external form, $parameters are passed without quotation marks'', #parameters are passed with quotation marks''.
  3. $passing parameter exists sql injection, # does not exist.
  4. $ can be used to make dynamic columns and complete the development of dynamic SQL.

  3. MyBatis result mapping (single table multi-table query)

<resultMap id="BaseResultMap" type="com.xzs.model.Book">
        <constructor>
            <idArg column="bid" jdbcType="INTEGER" javaType="java.lang.Integer"/>
            <arg column="bname" jdbcType="VARCHAR" javaType="java.lang.String"/>
            <arg column="price" jdbcType="REAL" javaType="java.lang.Float"/>
        </constructor>
    </resultMap>

In this code, the column attribute writes the fields in the database . There is a name attribute in it, which is the field in the entity class . When the fields in the database are the same as the fields in the entity class, there is no need to write the name attribute;

If there are underscores in the database, such as data_time , you need to add

<arg column="data_time",name="DataTime" jdbcType="VARCHAR" javaType="java.lang.String"/>

 Various scenarios using mybatis

In various scenarios using mybatis, the returned results are diverse, resultType/resultMap?

  1. To return the corresponding entity class of a single table, there is only one query result, and you can use resultType/resultMap.
  2. ResultType is used

     <select id="selectresultType" resultType="com.xzs.model.Book" parameterType="java.lang.Integer">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
            where bid = #{bid,jdbcType=INTEGER}
        </select>

    2. Write an interface to implement the interface
     

    Book selectresultType(Integer bid);
        @Override
        public Book selectresultType(Integer bid) {
            return bookMapper.selectresultType(bid);
        }

    3.Test method
     

        @Test
        public void selectresultType() {
            System.out.println("测试resultType查询");
            Book book = bookbiz.selectByPrimaryKey(12);
            System.out.println(book);
        }

    4.Test results

     

     

    2. To return the corresponding entity class of a single table, if there are multiple query results, you can use resultType/resultMap
    1.resultType/resultMap. One or more resultTypes use entity objects
     

    <select id="selectresultType01" resultType="com.xzs.model.Book">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
        </select>
     
        <select id="selectresultMap01" resultMap="BaseResultMap">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
        </select>

    2. Write interface methods and implement interfaces
     

        List<Book> selectresultType01();
     
        List<Book> selectresultMap01();
    @Override
        public List<Book> selectresultType01() {
            return bookMapper.selectresultType01();
        }
     
        @Override
        public List<Book> selectresultMap01() {
            return bookMapper.selectresultMap01();
        }

    3.Test method
     

        @Test
        public void selectresultType01() {
            bookbiz.selectresultType01().forEach(System.out::println);
        }
     
        @Test
        public void selectresultMap01() {
            bookbiz.selectresultMap01().forEach(System.out::println);
        }

    4.The test results are the same

     

     3. Return the corresponding entity class of multiple tables, and there is only one query result. Usually, resultType is used, but resultMap can also be used. 4. Return the
    corresponding entity class of multiple tables, and there are multiple query results. Usually, resultType is used, but resultMap can also be used.
    1. Write configuration, we don’t need to configure the table, we can call other tables |
     

    <select id="select01" resultType="java.util.Map" parameterType="java.util.Map">
            select s.*, sc.cid, sc.score
            from t_mysql_student s,
                 t_mysql_score sc
            where s.sid = sc.sid
              and sc.sid = #{sid}
              and sc.cid = #{cid}
        </select>
     
        <select id="select02" resultType="java.util.Map" parameterType="java.util.Map">
            select s.*, sc.cid, sc.score
            from t_mysql_student s,
                 t_mysql_score sc
            where s.sid = sc.sid
        </select>

    2. Write interfaces and implementation classes
     

        Map select01(Map map);
     
        List<Map> select02(Map map);
        @Override
        public Map select01(Map map) {
            return bookMapper.select01(map);
        }
     
        @Override
        public List<Map> select02(Map map) {
            return bookMapper.select02(map);
        }

    3.Test method
     

        @Test
        public void select01() {
            Map map = new HashMap();
            map.put("sid", "01");
            map.put("cid", "01");
            System.out.println(bookbiz.select01(map));
        }
     
        @Test
        public void select02() {
            Map map = new HashMap();
            map.put("sid", "01");
            map.put("cid", "01");
            bookbiz.select02(map).forEach(System.out::println);
        }

    4.Test results

     

     

     5. To return a single list, if there is only one query result, use resultType.
    6. To return a single list, if there are multiple query results, use resultType.
    1.Configure xml
     

    <!--单个-->
        <select id="selectByString01" resultType="java.lang.String" parameterType="java.lang.Integer">
            select bname
            from t_mvc_book
            where bid = #{bid,jdbcType=INTEGER}
        </select>
        <!--多个-->
        <select id="selectByString02" resultType="java.lang.String" parameterType="java.lang.String">
            select bname
            from t_mvc_book
            where bname like concat('%', #{bname}, '%')
        </select>

    2. Write interfaces and implement interfaces
     

        String selectByString01(Integer bid);
     
        List<String> selectByString02(String bname);
      @Override
        public String selectByString01(Integer bid) {
            return bookMapper.selectByString01(bid);
        }
     
        @Override
        public List<String> selectByString02(String bname) {
            return bookMapper.selectByString02(bname);
        }

    3.Test method
     

        @Test
        public void selectByString01() {
            System.out.println(bookbiz.selectByString01(60));
        }
     
        @Test
        public void selectByString02() {
            Map map = new HashMap();
            map.put("sid", "01");
            map.put("cid", "01");
            bookbiz.selectByString02("圣墟").forEach(System.out::println);
        }

    4.Test results

     

     

     

resultType: corresponding return type.

resultMap: corresponds to the returned mapping relationship, which refers to the relationship between entity classes and data table fields.

Single table query returns a single column, and multi-table query results are returned using resultType.

The result of the query needs to reflect the relevant attributes, then use resultMap

1, pagination

1. Introduction to PageHelper

PageHelper is a plug-in of Mybatis, which I won’t go into here, just to make paging queries         more convenient .

Official website: MyBatis paging plug-in PageHelper

Advantages of PageHelper plugin:

Physical paging: supports 12 common databases Oracle, MySql, MariaDB, SQLite, DB2, PostgreSQL, SqlServer, etc...
Supports multiple paging methods: supports common RowBounds (PageRowBounds), PageHelper.startPage method call, Mapper interface parameter call .
QueryInterceptor specification : Using the QueryInterceptor specification, it is easier to develop plug-ins.

2. Use of PageHelper

 1. Import pom dependencies

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
        </dependency>

2. Mybatis.cfg.xml configures the interceptor

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>

It must be configured on <environments>, otherwise an error will be reported.

Correct example:

mock test

mayBatis.xml configuration

 <select id="like4" resultType="com.xzs.model.Book"  parameterType="java.util.List">
    select
    <include refid="Base_Column_List" />
    from t_mvc_book
    where bname like Concat ('%',#{bname},'%')
  </select>

 interface

 List<Book> like4(String bname, PageBean pageBean);

 implement interface

 public List<Book> like4(String bname, PageBean pageBean) {
        if (pageBean!=null&&pageBean.isPagination()){
            PageHelper.startPage(pageBean.getPage(),pageBean.getRows());
        }
        List<Book> books = bookmapper.like4(bname);
        if (pageBean!=null&&pageBean.isPagination()){
            PageInfo<Book> bookPageInfo = new PageInfo<>(books);
            System.out.println("当前页" + bookPageInfo.getPageNum());
            System.out.println("展示记录数:" + bookPageInfo.getPageSize());
            System.out.println("符合查询条件的总记录数" + bookPageInfo.getTotal());
            pageBean.setTotal((int) bookPageInfo.getTotal());
        }
        return books ;
    }

 Test class:

 public void like4() {
        PageBean pageBean = new PageBean();
        pageBean.setPage(2);
        pageBean.setRows(10);
        BookBiz.like4("%圣%",pageBean).forEach(System.out::println);
    }

 result:

 3. Special character processing

  As we all know, in mybatis we often use special character dynamic splicing statements, such as greater than (>, >=), less than (<, <=), not equal to (<>,!=) symbols. The *.xml file format used by Mybatis requires related escaping of angle brackets or the use of CDATA sections.

 1. Use escape characters

Special characters escape character
< &lt;
> &gt;
& &amp;
" &quot;
&apos;
<= &lt;=
>= &gt;=

For example:

    <select id="listPager" resultType="java.util.Map" parameterType="java.util.Map">
        select * from t_mvc_book where price &lt; 9 and price &gt; 20
    </select>

 

2. Use CDATA sections

<![CDATA[ ]]> is XML syntax. All content inside <![CDATA[ ]]> will be ignored by the parser and will not be escaped. So this is a common scheme in xml.

 

Special characters <![CDATA[ ]]>
< <![CDATA[<]]>
> <![CDATA[>]]>
& <![CDATA[&]]>
" <![CDATA["]]>
<![CDATA[']]>
<= <![CDATA[<=]]>
>= <![CDATA[>=]]>
!= <![CDATA[!=]]>

For example:

   <select id="listPager" resultType="java.util.Map" parameterType="java.util.Map">
        select * from t_mvc_book where  <![CDATA[ price > #{price} and #{price} != 0 ]]>
    </select>

Guess you like

Origin blog.csdn.net/weixin_72997875/article/details/132441325