Mybatis+MySQL动态分页查询数据经典案例(含代码以及测试)
开发人员: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()); } }
执行完成之后,分页的信息,上一页,下一页,总页数等等都可以正常显示出来,但是,只有数据库里面的数据没有显示出来(调试如图所示):
集合里面是空的!!!
出现错误之后我就开始解决,于是写了个测试查询全部的房屋信息的方法,测试了一遍之后,果然不出所料,查出来的都是null,更为奇怪的是:数据库中有34条记录,而程序运行后查询出来的是34个null,对没错,就是34个null,一个也不多,一个也不少!!!
但是还很纳闷,于是各种假设各种调试,还是不行,当我吧问题发在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'
,嘴里骂了一句之后,拿起水杯干了一杯普利斯,挽起袖子就开始调试!我就不信还解决不了你了,
慢慢的。。。慢慢的,时间过来20分钟之后终于找出来了,原来是类型错了!我给大家看看错误代码和正确代码:
错误代码:
大家注意红色框中的代码,我取的是对象,而后面赋值的却是id,怪不得报错!!!
正确的代码如下:
还是老规矩,看红框中的代码,去掉getId()就可以正常运行了!!!
还有其他的好多细节错误来着,这里就不具体详细说了,要想查看完整的分页动态查询代码,请移步到 1111的博客 这里去看,希望对大家有帮助!