【MyBatis】动态SQL和mybatis分页的运用

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
可观测链路 OpenTelemetry 版,每月50GB免费额度
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 如果我们的前台没有传参,比如没有传入我们的name值,name就会把字段值改为null,这就违背了我们编码的初衷。许多人会使用类似于where 1 = 1来作为前缀,在代码中会用if,再用and进行一个sql拼接。


一、mybatis动态SQL

update 表名 set name=?,age=? where id=?
image.gif

如果我们的前台没有传参,比如没有传入我们的name值,name就会把字段值改为null,这就违背了我们编码的初衷。

许多人会使用类似于where 1 = 1来作为前缀,在代码中会用if判断是否为null,再用and进行一个sql拼接。

我们可以用常用的几个标签:

1、if

if标签里面,test里面的条件满足了,才会把后面的sql语句进行拼接

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

image.gif

2、foreach

我们再调用删除的方法的时候,通常会与SQL语句中的IN查询条件结合使用。

delete from student where id in()
image.gif

parameterType为List(链表)或者Array(数组),后面在引用时,参数名必须为list或者array。如在foreach标签中,collection属性则为需要迭代的集合,由于入参是个List,所以参数名必须为list。

<select id="selectById" resultType="com.tgq.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>
image.gif

测试一下结果

@Test
    public void selectById() {
        List<Integer> bids = Arrays.asList(new Integer[]{30, 31, 32, 33});
        bookbiz.selectById(bids).forEach(System.out::println);
    }
image.gif

image.gif编辑

3、choose、when、otherwise

你可以使用choosewhenotherwise元素来实现类似于switch语句的逻辑。

<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>
image.gif

如果传入的id不为空,则会在SQL语句中包含AND id = #{id}这个条件;如果传入的name不为空,则会在SQL语句中包含AND name = #{name}这个条件;否则,会在SQL语句中包含AND status = 'active'这个条件。

二、mybatis模糊查询

我们写入一个xml文件,log4j2.xml 用于打印出来你的sql语句

<?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>
image.gif

image.gif编辑

1、mybatis模糊查询的三种方式

    1. 第一种
    <select id="like01" resultType="com.tgq.model.Book" parameterType="java.util.List">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
            where bname like #{bname}
        </select>
    1. image.gif测试的结果
    @Test
        public void like01() {
            bookbiz.like01("%圣%").forEach(System.out::println);
        }
    1. image.gifimage.gif编辑
    2. 第二种:$需要单引号,$传参是占位符的形式

    <select id="like02" resultType="com.tgq.model.Book" parameterType="java.util.List">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
            where bname like '${bname}'
        </select>
    1. image.gif 测试的结果
    @Test
        public void like02() {
            bookbiz.like02("%圣%").forEach(System.out::println);
        }
    1. image.gifimage.gif编辑
    2. 第三种

    <select id="like03" resultType="com.tgq.model.Book" parameterType="java.util.List">
            select
            <include refid="Base_Column_List"/>
            from t_mvc_book
            where bname like concat('%',#{bname},'%')
        </select>
    1. image.gif 测试的结果
    @Test
        public void like03() {
            bookbiz.like03("%圣%").forEach(System.out::println);
        }
    1. image.gifimage.gif编辑

    2、mybatis中#与$的区别

      1. $是占位符赋值,#是预处理SQL。
      2. 外在形式,$传参不带引号''#传参自带引号''
      3. $传参存在sql注入,#不存在。
      4. $可以用来做动态列,完成动态sql的开发。

      三、MyBatis结果映射(单表多表查询)

      <resultMap id="BaseResultMap" type="com.tgq.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>
      image.gif

      这个代码中,column属性写的是数据库里面的字段,里面有一个name的属性,是实体类里面的字段,当数据库里面的字段喝实体类里面的字段是一样的可以不用写name属性;

      如果数据库里面出现了下划线,比如data_time,就需要在

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

      使用mybatis的各种场景

      使用mybatis的各种场景,返回的结果是多样的,resultType/resultMap

        1. 返回单表的对应的实体类,仅有一个查询结果,可以用resultType/resultMap。
          • 使用了resultType
          <select id="selectresultType" resultType="com.tgq.model.Book" parameterType="java.lang.Integer">
                  select
                  <include refid="Base_Column_List"/>
                  from t_mvc_book
                  where bid = #{bid,jdbcType=INTEGER}
              </select>
          • image.gif
          • 编写接口实现接口
          Book selectresultType(Integer bid);
          • image.gif
          @Override
              public Book selectresultType(Integer bid) {
                  return bookMapper.selectresultType(bid);
              }
          • image.gif
          • 测试方法
          @Test
              public void selectresultType() {
                  System.out.println("测试resultType查询");
                  Book book = bookbiz.selectByPrimaryKey(12);
                  System.out.println(book);
              }
          • image.gif
          • 测试结果image.gif编辑
            1. 返回单表的对应的实体类,有多个查询结果,可以用resultType/resultMap。
              • resultType/resultMap。resultType一个或多个都用实体对象
              <select id="selectresultType01" resultType="com.tgq.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>
              • image.gif
              • 编写接口方法和实现接口
              List<Book> selectresultType01();
                  List<Book> selectresultMap01();
              • image.gif
              @Override
                  public List<Book> selectresultType01() {
                      return bookMapper.selectresultType01();
                  }
                  @Override
                  public List<Book> selectresultMap01() {
                      return bookMapper.selectresultMap01();
                  }
              • image.gif
              • 测试方法
              @Test
                  public void selectresultType01() {
                      bookbiz.selectresultType01().forEach(System.out::println);
                  }
                  @Test
                  public void selectresultMap01() {
                      bookbiz.selectresultMap01().forEach(System.out::println);
                  }
              • image.gif
              • 测试结果是一样的image.gif编辑
                1. 返回多表的对应的实体类,仅有一个查询结果,通常用resultType,也可以用resultMap。
                2. 返回多表的对应的实体类,有多个查询结果,通常用resultType,也可以用resultMap。
                  • 编写配置,我们可以不用配置的表,可以调用其他的表
                  <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>
                  • image.gif
                  • 编写接口和实现类
                  Map select01(Map map);
                      List<Map> select02(Map map);
                  • image.gif
                  @Override
                      public Map select01(Map map) {
                          return bookMapper.select01(map);
                      }
                      @Override
                      public List<Map> select02(Map map) {
                          return bookMapper.select02(map);
                      }
                  • image.gif
                  • 测试方法
                  @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);
                      }
                  • image.gif
                  • 测试结果
                    image.gif编辑
                    image.gif编辑
                    1. 返回单个列表,仅有一个查询结果,就用resultType。
                    2. 返回单个列表,有多个查询结果,就用resultType。
                      • 配置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>
                      • image.gif
                      • 编写接口和实现接口
                      String selectByString01(Integer bid);
                          List<String> selectByString02(String bname);
                      • image.gif
                      @Override
                          public String selectByString01(Integer bid) {
                              return bookMapper.selectByString01(bid);
                          }
                          @Override
                          public List<String> selectByString02(String bname) {
                              return bookMapper.selectByString02(bname);
                          }
                      • image.gif
                      • 测试方法
                      @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);
                          }
                      • image.gif
                      • 测试结果image.gif编辑

                        image.gif编辑

                        resultType:对应返回类型。

                        resultMap:对应返回映射关系,指的是实体类与数据表字段关系。

                        单表查询,返回单列,返回多表查询结果,是用resultType

                        查询的结果,需要有关属性的体现,那么就用resultMap

                        四、mybatis分页

                        快速实现mybatis分页

                        1、利用sql和map

                        我们首先在我们的配置xml里面编写sql

                        <select id="selectFy01" resultType="com.tgq.model.Book" parameterType="java.util.Map">
                                select
                                <include refid="Base_Column_List"/>
                                from t_mvc_book
                                where bname like #{bname} limit #{start},#{size}
                            </select>
                        image.gif

                        编写我们的接口并且实现我们的接口

                        List<Book> selectFy01(Map map);
                        image.gif
                        @Override
                            public List<Book> selectFy01(Map map) {
                                return bookMapper.selectFy01(map);
                            }
                        image.gif

                        测试方法

                        @Test
                            public void selectFy01() {
                                Map map = new HashMap();
                                map.put("bname", "%圣墟%");
                                map.put("start", 10);
                                map.put("size", 10);
                                bookbiz.selectFy01(map).forEach(System.out::println);
                            }
                        image.gif

                        image.gif编辑

                        2、利用分页插件

                        因为我们的Mybatis的分页功能很弱,它是基于内存的分页(查出所有记录再按偏移量offset和边界limit取结果),在大数据量的情况下这样的分页基本上是没有用的。

                        编写一个分页类

                        package com.tgq.utils;
                        import javax.servlet.http.HttpServletRequest;
                        import java.io.Serializable;
                        import java.util.Map;
                        public class PageBean implements Serializable {
                          private static final long serialVersionUID = 2422581023658455731L;
                          //页码
                          private int page=1;
                          //每页显示记录数
                          private int rows=10;
                          //总记录数
                          private int total=0;
                          //是否分页
                          private boolean isPagination=true;
                          //上一次的请求路径
                          private String url;
                          //获取所有的请求参数
                          private Map<String,String[]> map;
                          public PageBean() {
                            super();
                          }
                          //设置请求参数
                          public void setRequest(HttpServletRequest req) {
                            String page=req.getParameter("page");
                            String rows=req.getParameter("rows");
                            String pagination=req.getParameter("pagination");
                            this.setPage(page);
                            this.setRows(rows);
                            this.setPagination(pagination);
                            this.url=req.getContextPath()+req.getServletPath();
                            this.map=req.getParameterMap();
                          }
                          public String getUrl() {
                            return url;
                          }
                          public void setUrl(String url) {
                            this.url = url;
                          }
                          public Map<String, String[]> getMap() {
                            return map;
                          }
                          public void setMap(Map<String, String[]> map) {
                            this.map = map;
                          }
                          public int getPage() {
                            return page;
                          }
                          public void setPage(int page) {
                            this.page = page;
                          }
                          public void setPage(String page) {
                            if(null!=page&&!"".equals(page.trim()))
                              this.page = Integer.parseInt(page);
                          }
                          public int getRows() {
                            return rows;
                          }
                          public void setRows(int rows) {
                            this.rows = rows;
                          }
                          public void setRows(String rows) {
                            if(null!=rows&&!"".equals(rows.trim()))
                              this.rows = Integer.parseInt(rows);
                          }
                          public int getTotal() {
                            return total;
                          }
                          public void setTotal(int total) {
                            this.total = total;
                          }
                          public void setTotal(String total) {
                            this.total = Integer.parseInt(total);
                          }
                          public boolean isPagination() {
                            return isPagination;
                          }
                          public void setPagination(boolean isPagination) {
                            this.isPagination = isPagination;
                          }
                          public void setPagination(String isPagination) {
                            if(null!=isPagination&&!"".equals(isPagination.trim()))
                              this.isPagination = Boolean.parseBoolean(isPagination);
                          }
                          /**
                           * 获取分页起始标记位置
                           * @return
                           */
                          public int getStartIndex() {
                            //(当前页码-1)*显示记录数
                            return (this.getPage()-1)*this.rows;
                          }
                          /**
                           * 末页
                           * @return
                           */
                          public int getMaxPage() {
                            int totalpage=this.total/this.rows;
                            if(this.total%this.rows!=0)
                              totalpage++;
                            return totalpage;
                          }
                          /**
                           * 下一页
                           * @return
                           */
                          public int getNextPage() {
                            int nextPage=this.page+1;
                            if(this.page>=this.getMaxPage())
                              nextPage=this.getMaxPage();
                            return nextPage;
                          }
                          /**
                           * 上一页
                           * @return
                           */
                          public int getPreivousPage() {
                            int previousPage=this.page-1;
                            if(previousPage<1)
                              previousPage=1;
                            return previousPage;
                          }
                          @Override
                          public String toString() {
                            return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", isPagination=" + isPagination
                                + "]";
                          }
                        }
                        image.gif

                        配置pom.xml文件

                        <dependency>
                            <groupId>com.github.pagehelper</groupId>
                            <artifactId>pagehelper</artifactId>
                            <version>5.1.2</version>
                        </dependency>
                        image.gif

                        配置mybatis.cfg.xml

                        <plugins>
                                <!-- 配置分页插件PageHelper, 4.0.0以后的版本支持自动识别使用的数据库 -->
                                <plugin interceptor="com.github.pagehelper.PageInterceptor">
                                </plugin>
                            </plugins>
                        image.gif

                        编写接口及接口实现类

                        List<Book> selectFy02(@Param("bname") String bname);
                        image.gif
                        @Override
                            public List<Book> selectFy02(String bname, PageBean pageBean) {
                                if (pageBean != null && pageBean.isPagination())
                                PageHelper.startPage(pageBean.getPage(),pageBean.getRows());
                                List<Book> books = bookMapper.selectFy02(bname);
                                if (pageBean != null && pageBean.isPagination()) {
                                    PageInfo<Book> info = new PageInfo<>(books);
                                    System.out.println("当前页:" + info.getPageNum());
                                    System.out.println("记录数:" + info.getPageSize());
                                    System.out.println("总记录数:" + info.getTotal());
                                    pageBean.setTotal((int) info.getTotal());
                                }
                                return books;
                            }
                        image.gif

                        测试方法

                        @Test
                            public void selectFy02() {
                                String bname = "圣墟";
                                PageBean pageBean = new PageBean();
                                pageBean.setPage(2);
                                pageBean.setRows(10);
                                bookbiz.selectFy02(bname, pageBean).forEach(System.out::println);
                            }
                        image.gif

                        image.gif编辑


                        image.gif编辑

                        五、mymatis特殊字符

                          1. pojo/entity/model:实体类
                          2. vo:view object 视图对象:专门用来展示        如:java.util.Map
                          3. dto:接受参数

                          我们在编写sql的时候会用<>

                          配置xml,如果要用<>,就必须用<![CDATA[]]>包裹起来,不然会报错

                          <select id="selectMinMax" resultType="com.tgq.model.Book" parameterType="com.tgq.dto.BookDto">
                                  select
                                  <include refid="Base_Column_List"/>
                                  from t_mvc_book
                                  where
                              <![CDATA[
                           price > #{min} and price < #{max}
                              ]]>
                              </select>
                          image.gif

                          我们的resultType可以使用BookDto ,里面有新的属性

                          package com.tgq.dto;
                          import com.tgq.model.Book;
                          /**
                           * @软件包名 com.tgq.dto
                           * @用户 tgq
                           * @create 2023-08-24 下午6:24
                           * @注释说明:
                           */
                          public class BookDto extends Book {
                              private float min;
                              private float max;
                              public float getMin() {
                                  return min;
                              }
                              public void setMin(float min) {
                                  this.min = min;
                              }
                              public float getMax() {
                                  return max;
                              }
                              public void setMax(float max) {
                                  this.max = max;
                              }
                          }
                          image.gif

                          编写接口和实现接口

                          List<Book> selectMinMax(BookDto bookDto);
                          image.gif
                          @Override
                              public List<Book> selectMinMax(BookDto bookDto) {
                                  return bookMapper.selectMinMax(bookDto);
                              }
                          image.gif

                          编写测试方法

                          @Test
                              public void selectMinMax() {
                                  BookDto bto = new BookDto();
                                  bto.setMin(20);
                                  bto.setMax(60);
                                  bookbiz.selectMinMax(bto).forEach(System.out::println);
                              }
                          image.gif

                          image.gif编辑

                           

                          当然我们的xml可以不用<![CDATA[]]>,<和>就需要用&gt;和&lt;代替

                          <select id="selectMinMax" resultType="com.tgq.model.Book" parameterType="com.tgq.dto.BookDto">
                                  select
                                  <include refid="Base_Column_List"/>
                                  from t_mvc_book
                                  where  price &gt; #{min} and price &lt; #{max}
                              </select>
                          image.gif

                          结果是一样的

                          image.gif编辑

                          相关实践学习
                          如何在云端创建MySQL数据库
                          开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
                          全面了解阿里云能为你做什么
                          阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
                          相关文章
                          |
                          23天前
                          |
                          SQL XML Java
                          8、Mybatis-Plus 分页插件、自定义分页
                          这篇文章介绍了Mybatis-Plus的分页功能,包括如何配置分页插件、使用Mybatis-Plus提供的Page对象进行分页查询,以及如何在XML中自定义分页SQL。文章通过具体的代码示例和测试结果,展示了分页插件的使用和自定义分页的方法。
                          8、Mybatis-Plus 分页插件、自定义分页
                          |
                          23天前
                          |
                          SQL Java 测试技术
                          3、Mybatis-Plus 自定义sql语句
                          这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
                          3、Mybatis-Plus 自定义sql语句
                          |
                          17天前
                          |
                          SQL Java 数据库连接
                          Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
                          文章讲述了在使用Mybatis时遇到的资源文件找不到的问题,并提供了通过修改Maven配置来解决资源文件编译到target目录下的方法。
                          Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
                          |
                          1月前
                          |
                          SQL 关系型数据库 MySQL
                          SQL中如何实现分页?
                          【8月更文挑战第3天】SQL中如何实现分页?
                          73 36
                          |
                          7天前
                          |
                          SQL XML Java
                          mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
                          当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
                          14 1
                          |
                          17天前
                          |
                          SQL Java 数据库连接
                          Mybatis系列之 动态SQL
                          文章详细介绍了Mybatis中的动态SQL用法,包括`<if>`、`<choose>`、`<when>`、`<otherwise>`、`<trim>`和`<foreach>`等元素的应用,并通过实际代码示例展示了如何根据不同条件动态生成SQL语句。
                          |
                          17天前
                          |
                          SQL Java 关系型数据库
                          SpringBoot 系列之 MyBatis输出SQL日志
                          这篇文章介绍了如何在SpringBoot项目中通过MyBatis配置输出SQL日志,具体方法是在`application.yml`或`application.properties`中设置MyBatis的日志实现为`org.apache.ibatis.logging.stdout.StdOutImpl`来直接在控制台打印SQL日志。
                          SpringBoot 系列之 MyBatis输出SQL日志
                          |
                          20天前
                          |
                          SQL 关系型数据库 MySQL
                          解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
                          该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
                          |
                          23天前
                          |
                          Java 数据库 Spring
                          MyBatisPlus分页插件在SpringBoot中的使用
                          这篇文章介绍了如何在Spring Boot项目中配置和使用MyBatis-Plus的分页插件,包括创建配置类以注册分页拦截器,编写测试类来演示如何进行分页查询,并展示了测试结果和数据库表结构。
                          MyBatisPlus分页插件在SpringBoot中的使用
                          |
                          10天前
                          |
                          SQL Java 关系型数据库
                          MyBatis-Plus 分页魅力绽放!紧跟技术热点,带你领略数据分页的高效与便捷
                          【8月更文挑战第29天】在 Java 开发中,数据处理至关重要,尤其在大量数据查询与展示时,分页功能尤为重要。MyBatis-Plus 作为一款强大的持久层框架,提供了便捷高效的分页解决方案。通过封装数据库分页查询语句,开发者能轻松实现分页功能。在实际应用中,只需创建 `Page` 对象并设置页码和每页条数,再通过 `QueryWrapper` 构建查询条件,调用 `selectPage` 方法即可完成分页查询。MyBatis-Plus 不仅生成分页 SQL 语句,还自动处理参数合法性检查,并支持条件查询和排序等功能,极大地提升了系统性能和稳定性。
                          26 0
                          下一篇
                          DDNS