Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)

   最近在用Mybatis做项目的时候遇到了不少问题,今天我就在这和大家分享一下,稀稀拉拉的研究了两天,终于搞好了!


    开发人员:1111


    开发软件:Myeclipse


    用到的框架技术:Mybatis


    数据库:MySql


    主要内容:动态分页查询数据



      好了,现在开始演示,我先把代码贴上来以便大家的理解:


mybatis-config.xml的主要配置内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
    <!-- 动态查询房屋信息的条件类 -->
    <typeAlias type="cn.bdqn.mhouse.entity.HouseCondition" alias="houseC"/>
    <typeAlias type="cn.bdqn.mhouse.util.Page" alias="page"/>
    <!-- 区县别名 -->
    <typeAlias type="cn.bdqn.mhouse.entity.District" alias="district"/>
    <typeAlias type="cn.bdqn.mhouse.dao.IDistrictDao" alias="districtDao"/>
    <!-- 房屋信息的别名 -->
    <typeAlias type="cn.bdqn.mhouse.entity.House" alias="house"/>
    <typeAlias type="cn.bdqn.mhouse.dao.IHouseDao" alias="houseDao"/>
    <!-- 街道信息的别名 -->
    <typeAlias type="cn.bdqn.mhouse.entity.Street" alias="street"/>
    <typeAlias type="cn.bdqn.mhouse.dao.IStreetDao" alias="streetDao"/>
    <!-- 房屋类型的别名 -->
    <typeAlias type="cn.bdqn.mhouse.entity.Types" alias="types"/>
    <typeAlias type="cn.bdqn.mhouse.dao.ITypesDao" alias="typesDao"/>
    <!-- 用户信息的别名 -->
    <typeAlias type="cn.bdqn.mhouse.entity.Users" alias="users"/>
    <typeAlias type="cn.bdqn.mhouse.dao.IUsersDao" alias="usersDao"/>
  </typeAliases>
  <environments default="Mysqldevelopment">
    <!-- oracle的数据库配置  -->
    <environment id="Oracledevelopment">
    <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
      <property name="driver" value="oracle.jdbc.OracleDriver"/>
      <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
      <property name="username" value="scott"/>
      <property name="password" value="123"/>
      </dataSource>
    </environment>
    <!-- mysql的数据库配置 -->
    <environment id="Mysqldevelopment">
    <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
      <property name="driver" value="com.mysql.jdbc.Driver"/>
      <property name="url" value="jdbc:mysql://192.168.1.128:3306/house"/>
      <property name="username" value="root"/>
      <property name="password" value="171268"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="cn/bdqn/mhouse/dao/DistrictDaoMapper.xml"/>
    <mapper resource="cn/bdqn/mhouse/dao/HouseDaoMapper.xml"/>
    <mapper resource="cn/bdqn/mhouse/dao/StreetDaoMapper.xml"/>
    <mapper resource="cn/bdqn/mhouse/dao/TypesDaoMapper.xml"/>
    <mapper resource="cn/bdqn/mhouse/dao/UsersDaoMapper.xml"/>
  </mappers>
</configuration>


由于分页查询得用到总记录数,所以我写了两个方法来实现的,第一个是动态查询数据总记录数,接下来大家看看impl类和相对应的Mapper.xml配置信息吧,由于dao接口是由impl实现类来实现的,所以在这我就不给大家放dao层接口的代码了:



     动态查询数据的impl代码:

/**
   * (非 Javadoc)
  * <p>Title: reCount</p>
  * <p>Description(描述):动态查询总计录数</p>
  * @param housec
  * @return
  * @see cn.bdqn.mhouse.dao.IHouseDao#reCount(cn.bdqn.mhouse.entity.HouseCondition)
   */
  @Override
  public int reCount(HouseCondition housec) {
    SqlSession session=MybatisUtil.getSession();
    Integer count=(Integer)session.selectOne("houseDao.reCount",housec);
    return count;
  }

代码中的MybatisUtils是mybatis的工具类,动态查询数据方法在Mapper.xml里面的配置详情代码:

 <!-- 动态查询房屋信息的总记录数 -->
  <select id="reCount" parameterType="houseC" resultType="Integer">
  select count(0) from house h
  <where>
    <if test="priceBegin!=null">
       and h.price > #{priceBegin}
    </if>
    <if test="priceEnd!=null">
      and h.price   <![CDATA[<]]>  #{priceEnd}
    </if>
    <!-- h.street_id是数据库的字段名 -->
    <if test="street!=null">
       and h.street_id = #{street.id}
     </if>
     <!-- h.type_id是数据库的字段名 -->
     <if test="types!=null">
       and h.type_id = #{types.id}  
     </if> 
    <if test="floorageBegin!=null">
       and h.floorage > #{floorageBegin}  
    </if>
    <if test="floorageEnd!=null">
      and h.floorage <![CDATA[<]]>  #{floorageEnd}
    </if>
  </where>
  </select>

 然后我把表与表之间的关联映射在放上来供大家看看:

 

  <resultMap id="BaseResultMap" type="house" >
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="TITLE" property="title" jdbcType="VARCHAR" />
    <result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
    <result column="PRICE" property="price" jdbcType="REAL" />
    <result column="PUBDATE" property="pubdate" jdbcType="DATE" />
    <result column="FLOORAGE" property="floorage" jdbcType="INTEGER" />
    <result column="CONTACT" property="contact" jdbcType="VARCHAR" />
    <!-- 开始映射外键 -->
    <!-- 映射用户表 -->
    <association property="users" column="user_id" select="selectUsers"/>
    <!-- 映射类型表 -->
    <association property="types" column="type_id" select="selectTypes"/>
    <!-- 映射街道表 -->
    <association property="street" column="street_id" select="selectStreet"/>
  </resultMap>
  <!-- 关联用户表 -->
  <resultMap id="usersMapper" type="users" >
    <id column="ID" property="id" jdbcType="INTEGER" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
    <result column="PASSWORD" property="password" jdbcType="VARCHAR" />
    <result column="TELEPHONE" property="telephone" jdbcType="VARCHAR" />
    <result column="USERNAME" property="username" jdbcType="VARCHAR" />
    <result column="ISADMIN" property="isadmin" jdbcType="VARCHAR" />
  </resultMap>
  <!-- 关联街道表 -->
  <resultMap id="streetMapper" type="street" >
    <id column="ID" property="id" />
    <result column="NAME" property="name" jdbcType="VARCHAR" />
  <association property="district" column="district_id" select ="selectDirstrict"/>
  </resultMap>
  <!-- 关联区县表 -->
    <resultMap id="districtDaoMapper" type="district" >
      <id column="ID" property="id"/>
      <result column="NAME" property="name"/>
   </resultMap>
     <!-- 在根据区县id查询一遍区县表 -->
      <select id="selectDirstrict" resultMap="districtDaoMapper">
        select * form district where id=#{district_id}  
      </select>
  <!--关联类型表  -->
  <resultMap id="typeMapper" type="types" >
      <id column="ID" property="id"/>
      <result column="NAME" property="name" jdbcType="VARCHAR" />
   </resultMap>
  <!-- 用户表 -->
  <select id="selectUsers" resultMap="usersMapper">
    select * from users where id=#{user_id}
  </select>
  <!-- 街道表 -->
   <select id="selectStreet" resultMap="streetMapper">
    select * from street where id=#{street_id}
  </select>
  <!-- 类型表 -->
    <select id="selectTypes" resultMap="typeMapper">
    select * from types where id=#{type_id}
  </select>
  <sql id="Base_Column_List" >
    ID, USER_ID, TYPE_ID, TITLE, DESCRIPTION, PRICE, PUBDATE, FLOORAGE, CONTACT, STREET_ID
  </sql>

上面都有相对应的注释,在这就不多做解释了,

 

            总记录数现在查询出来了,就开始动态分页查询数据了,首先得用到一个分页类Page,分页类的代码:

package cn.bdqn.mhouse.util;
import java.util.ArrayList;
import java.util.List;
import cn.bdqn.mhouse.entity.House;
/**
 * 
*    
* 项目名称:mhouse   
* 类名称:Page   
* 类描述:   分页的工具类
* 创建人:Mu Xiongxiong  
* 创建时间:2017-3-17 下午1:04:02   
* 修改人:Mu Xiongxiong   
* 修改时间:2017-3-17 下午1:04:02   
* 修改备注:   
* @version    
*
 */
public class Page {
  private int pageSize=3;            //页大小
  private int pageIndex=0;           //当前页号
  private int totalPageCount=0;      //总页数
  private int record=0;              //记录总数
  private Integer nextPage;          //下一页
  private Integer prePage;           //上一页
  private List<House> houseList=new ArrayList<House>();     //房屋信息的集合
  /**    
   * @author Mu Xiongxiong       
   * @created 2017-3-17 下午10:04:41 
   * @return type 
   */
  public List<House> getHouseList() {
    return houseList;
  }
  /**     
   * @author Mu Xiongxiong      
   * @created 2017-3-17 下午10:04:41         
   * @param houseList   
   */
  public void setHouseList(List<House> houseList) {
    this.houseList = houseList;
  }
  //得到开始记录数
  public int getSartRow(){
    return (pageIndex-1)*pageSize;
  }
  //得到结束记录数
  public int getEndRow(){
    return pageSize;
  }
  public int getPageSize() {
    return pageSize;
  }
  public void setPageSize(int pageSize) {
    this.pageSize = pageSize;
  }
  public int getPageIndex() {
    return pageIndex;
  }
  //得到当前页
  public void setPageIndex(int pageIndex) {
    this.pageIndex = pageIndex;
    //下一页
    setNextPage();
    //上一页
    setPrePage();
  }
  public int getTotalPageCount() {
    return totalPageCount;
  }
  //总页数
  public void setTotalPageCount() {
    int totalP = record % getPageSize() == 0 ? record / getPageSize() :
      record/ getPageSize() + 1;
    this.totalPageCount = totalP;
  }
  public int getRecord() {
    return record;
  }
  //总记录数
  public void setRecord(int record) {
    this.record = record;
    //设置总页数
    setTotalPageCount();
  }
  public Integer getNextPage() {
    return nextPage;
  }
  //设置下一页
  public void setNextPage() {
    this.nextPage = this.pageIndex+1;
  }
  public Integer getPrePage() {
    return prePage;
  }
  //设置上一页
  public void setPrePage() {
    this.prePage =this.pageIndex-1;
    if(this.prePage<1){
      this.prePage=1;
    }
  }
}

现在分页的工具类也出来了,就差分页查询数据了,先看impl里面的方法:

 

  /**
   * (非 Javadoc)
  * <p>Title: getHouseInfoByDymanic</p>
  * <p>Description:‘动态分页查询房屋信息</p>
  * @param housec
  * @param pageIndex
  * @return
  * @see cn.bdqn.mhouse.dao.IHouseDao#getHouseInfoByDymanic(cn.bdqn.mhouse.entity.HouseCondition, int)
   */
  @Override
  public Page getHouseInfoByDymanic(HouseCondition housec,int pageIndex) {
    Page page=new Page();
    page.setPageIndex(pageIndex);      //当前页
    int reCount=reCount(housec);       
    page.setRecord(reCount);           //总记录数
    List<House> houseList=new ArrayList<House>();
    HashMap parMap=new HashMap();
    parMap.put("priceBegin",housec.getPriceBegin());
    parMap.put("priceEnd",housec.getPriceEnd());
    if(housec.getStreet()!=null){
    parMap.put("street",housec.getStreet());
    }
    if(housec.getTypes()!=null){
      parMap.put("types",housec.getTypes());
    }
    parMap.put("floorageBegin", housec.getFloorageBegin());
    parMap.put("floorageEnd",housec.getFloorageEnd());
    parMap.put("stratRow",page.getSartRow());
    parMap.put("endRow",page.getEndRow());
    SqlSession session=MybatisUtil.getSession();
    try {
      houseList=session.selectList("houseDao.getHouseInfoByDymanic",parMap);
      page.setHouseList(houseList);
    } catch (Exception e) {
      e.printStackTrace();
    }finally{
      MybatisUtil.closeSession();
    }
    return page;
  }

对应的Mapper.xml配置信息:

 

 

 <!-- 分页动态查询房屋信息 -->
  <select id="getHouseInfoByDymanic" parameterType="hashmap" resultMap="BaseResultMap">
      select * from house h
  <where>
    <if test="priceBegin!=null">
       and h.price > #{priceBegin}
    </if>
    <if test="priceEnd!=null">
      and h.price   <![CDATA[<]]>  #{priceEnd}
    </if>
    <if test="street!=null">
       and h.street_id = #{street.id}
     </if>
    <if test="types!=null||!types==null">
       and h.type_id = #{types.id}  
     </if>
    <if test="floorageBegin!=null">
       and h.floorage > #{floorageBegin}  
    </if>
    <if test="floorageEnd!=null">
      and h.floorage <![CDATA[<]]>  #{floorageEnd}
    </if>
  </where>
        limit #{stratRow},#{endRow}
  </select>

最后我写了test测试,看看能不能正常执行:test测试类的方法如下:

 

 

  /**
   * 
  * @Title: reCount
  * @Description: 该方法的主要作用:分页查询房屋信息
  * @param   设定文件  
  * @return  返回类型:void   
  * @throws
   */
  @Test
  public void getHouseInfoByDymanic(){
    Page page=new Page();
//    houseC.setPriceBegin(50);                      //起始价格
//    houseC.setPriceEnd(4000);                      //结束价格
//    houseC.setFloorageBegin(10);                   //起始面积
//    houseC.setFloorageEnd(6000);                   //最终面积
    types.setId(1003);                             //房屋类型
    houseC.setTypes(types);
    street.setId(1003);                //所在的街道
//    //street.setDistrict(district);
    houseC.setStreet(street);
    int pageIndex=3;
    page=houseDao.getHouseInfoByDymanic(houseC, pageIndex);
    System.out.println("当前页是:"+page.getPageIndex());
    System.out.println("下一页是:"+page.getNextPage());
    System.out.println("上一页是:"+page.getPrePage());
    System.out.println("总记录数:"+page.getRecord());
    System.out.println("总页数是:"+page.getTotalPageCount());
    System.out.println("页大小是:"+page.getPageSize());
    List<House> houselist=page.getHouseList();
    for (House house : houselist) {
      System.out.println("房屋标题:"+house.getTitle());
    }
  }

执行完成之后,分页的信息,上一页,下一页,总页数等等都可以正常显示出来,但是,只有数据库里面的数据没有显示出来(调试如图所示):

31.png

集合里面是空的!!!


      出现错误之后我就开始解决,于是写了个测试查询全部的房屋信息的方法,测试了一遍之后,果然不出所料,查出来的都是null,更为奇怪的是:数据库中有34条记录,而程序运行后查询出来的是34个null,对没错,就是34个null,一个也不多,一个也不少!!!

32.png

但是还很纳闷,于是各种假设各种调试,还是不行,当我吧问题发在csdn上面问的时候,忽然想起来了,原来是映射的resultType错了,我查询的是house,应该映射的是house实体类的权限定名,我写的是Page的全限定名,我写成page也不足为奇,因为我的返回类型就是page,   哎 ,就这个错,我弄了两小时才解决掉!!!实现是累的不行了!


     这个问题解决了之后,我就继续测试其他的功能,现在是数据数来了,但是正儿八经最主要的测试还没进行呢,汗,于是我就开始测试动态查询数据,一步一步的测试的时候,错又来了,我把错误信息贴上来大家看看:


org.apache.ibatis.exceptions.PersistenceException:

### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException:There is no getter for property named 'id' in 'class java.lang.Integer'

### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.lang.Integer'

33.png


,嘴里骂了一句之后,拿起水杯干了一杯普利斯,挽起袖子就开始调试!我就不信还解决不了你了,

          慢慢的。。。慢慢的,时间过来20分钟之后终于找出来了,原来是类型错了!我给大家看看错误代码和正确代码:

      错误代码:

34.png

大家注意红色框中的代码,我取的是对象,而后面赋值的却是id,怪不得报错!!!

      正确的代码如下:

35.png

 还是老规矩,看红框中的代码,去掉getId()就可以正常运行了!!!

     还有其他的好多细节错误来着,这里就不具体详细说了,要想查看完整的分页动态查询代码,请移步到 1111的博客 这里去看,希望对大家有帮助!
































































相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
Oracle 关系型数据库 MySQL
使用崖山YMP 迁移 Oracle/MySQL 至YashanDB 23.2 验证测试
这篇文章是作者尚雷关于使用崖山YMP迁移Oracle/MySQL至YashanDB 23.2的验证测试分享。介绍了YMP的产品信息,包括架构、版本支持等,还详细阐述了外置库部署、YMP部署、访问YMP、数据源管理、任务管理(创建任务、迁移配置、离线迁移、校验初始化、一致性校验)及MySQL迁移的全过程。
|
1月前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
228 43
|
1月前
|
存储 SQL 关系型数据库
MySQL底层概述—4.InnoDB数据文件
本文介绍了InnoDB表空间文件结构及其组成部分,包括表空间、段、区、页和行。表空间是最高逻辑层,包含多个段;段由若干个区组成,每个区包含64个连续的页,页用于存储多条行记录。文章还详细解析了Page结构,分为通用部分(文件头与文件尾)、数据记录部分和页目录部分。此外,文中探讨了行记录格式,包括四种行格式(Redundant、Compact、Dynamic和Compressed),重点介绍了Compact行记录格式及其溢出机制。最后,文章解释了不同行格式的特点及应用场景,帮助理解InnoDB存储引擎的工作原理。
MySQL底层概述—4.InnoDB数据文件
|
16天前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
35 9
|
22天前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
78 9
|
23天前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(09)数据磁盘存储模型 | 一行数据怎么存?
文中详细介绍了MySQL数据库中一行数据在磁盘上的存储机制,包括表空间、段、区、页和行的具体结构,以及如何设计和优化行数据存储以提高性能。
|
22天前
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
|
分布式计算 关系型数据库 MySQL
E-Mapreduce如何处理RDS的数据
目前网站的一些业务数据存在了数据库中,这些数据往往需要做进一步的分析,如:需要跟一些日志数据关联分析,或者需要进行一些如机器学习的分析。在阿里云上,目前E-Mapreduce可以满足这类进一步分析的需求。
4992 0
|
2月前
|
关系型数据库 MySQL 数据库连接
数据库连接工具连接mysql提示:“Host ‘172.23.0.1‘ is not allowed to connect to this MySQL server“
docker-compose部署mysql8服务后,连接时提示不允许连接问题解决
|
1月前
|
关系型数据库 MySQL 数据库
Docker Compose V2 安装常用数据库MySQL+Mongo
以上内容涵盖了使用 Docker Compose 安装和管理 MySQL 和 MongoDB 的详细步骤,希望对您有所帮助。
175 42

热门文章

最新文章