Mybatis实现条件查询(三)
1. 准备
请先完成Mybatis基本配置(一)的基本内容
2. 疑问我们再Mybatis基本配置(一)中实现了按照商品ID进行查询商品信息,可是在实际应用中却很少出现根据ID来查询商品的情况。因为我们的用户或许并不知道这个商品的ID是什么,他们只能记住商品编码或者商品的部分名称,更甚至是他们只记得这个商品的大致售价。如果这个时候他们想找到自己想要的那个商品该怎么办么?所以我们的系统还必须提供另外一些功能。
3. 解决
现在我们拟定我们的用户需要根据商品编码、商品名称及价格等信息来查询自己想要的商品,所以我们要做如下更改:
1) 定义查询条件实体类
package com.mybatis.entity; public class QryPartParam { private String partCode; //要查询的商品编码 private String partName; //要查询的商品名称 private float salePriceLow; //价格区间--起始价格 private float salePriceHigh; //价格区间--结束价格 public String getPartCode() { return partCode; } public void setPartCode(String partCode) { this.partCode=partCode; } public String getPartName() { return partName; } public void setPartName(String partName) { this.partName=partName; } public String getSalePriceLow() { return salePriceLow; } public void setSalePriceLow(String salePriceLow) { this.salePriceLow=salePriceLow; } public String getSalePriceHigh() { return salePriceHigh; } public void setSalePriceHigh(String SalePriceHigh) { this.SalePriceHigh=SalePriceHigh; } }
2)在com.mybatis.dao.PartDao中增加接口函数
public List<PartInfo> getPartInfoByUser(QryPartParam qryPartParam);
3)在com.mybatis.dao.mapper.PartMapper中增加其实现方法
<select id="getPartInfoByUser" parameterType="com.mybatis.entity.QryPartParam" resultType="com.mybatis.entity.PartInfo"> SELECT * FROM tbInfoPart WHERE PartCode = #{partCode} AND PartName LIKE '%'+#{partName}+'%' AND SalePrice <![CDATA[>=]]> #{salePriceLow} AND SalePrice <![CDATA[<=]]> #{salePriceHigh} </select>
要注意的是:
(1)需要模糊查询的时候,可参考PartName LIKE '%'+#{partName}+'%'这种的写法,当然还有其他写法就待读者自行摸索
(2)当我们的查询语句中出现>或者<等此类符号时,因为这两种符号为xml的关键字符,
"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。
">" 会产生错误,因为解析器会把该字符解释为新元素的结束。
所以需要特殊处理成<![CDATA[>=]]>。术语 CDATA 指的是不应由 XML 解析器进行解析的文本数据。
当然我们也可以用转义字符。xml的转义字符列表如下:
< | < | 小于 |
> | > | 大于 |
& | & | 和号 |
' | ' | 省略号 |
" | " | 引号 |
4)测试下效果
public static List<PartInfo> selectPartByUser(QryPartParam qryPartParam){ InputStream iStream = TestMain.class.getClassLoader().getResourceAsStream("mybatis.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(iStream); SqlSession session = sessionFactory.openSession(); String statement = "com.mybatis.dao.PartDao.getPartInfoByUser"; List<PartInfo> partInfos = session.selectList(statement, qryPartParam); session.close(); return partInfos; }
public static void main(String[] args) { QryPartParam qryPartParam = new QryPartParam(); qryPartParam.setPartCode("001-0001"); qryPartParam.setPartName("TCL"); qryPartParam.setSalePriceLow(0f); qryPartParam.setSalePriceHigh(10000f); List<PartInfo> partInfos = selectPartByUser(qryPartParam); for (PartInfo partInfo : partInfos) { System.out.println("ID:"+partInfo.getId()+" 商品:["+ partInfo.getPartCode()+"] "+ partInfo.getPartName()+" ,售价:"+ partInfo.getSalePrice()+"元/"+ partInfo.getUnit()); }
打印结果为
ID:1 商品:[001-0001] TCL D32E161 32英寸 内置wifi 在线影视 窄边LED网络液晶电视 ,售价:1099.9元/台
可以看到我们已经成功查询到了该条商品
4.有关参数问题
有人可能会问,按照现在参数定义方式(com.mybatis.entity.QryPartParam),那是不是说我以后每增加一个查询,就需要定义相对应的参数类?为了解决这个问题,笔者提供其他两种参数定义方式
1)通过@Param注解来标识多参数:
public List<PartInfo> getPartInfoByUser(@Param("partCode") String partCode,
@Param("partName") String partName,
@Param("salePriceLow") float salePriceLow,
@Param("salePriceHigh") float salePriceHigh);
在Mapper中则不再需要parameterType赋值:
<select id="getPartInfoByUser" resultType="com.mybatis.entity.PartInfo"> SELECT * FROM tbInfoPart WHERE PartCode = #{partCode} AND PartName LIKE '%'+#{partName}+'%' AND SalePrice <![CDATA[>=]]> #{salePriceLow} AND SalePrice <![CDATA[<=]]> #{salePriceHigh} </select>
此种传参方式适用于参数个数比较少的情况。
2)通过Map传参:
public List<PartInfo> getPartInfoByUser(Map<String, Object> map);
在Mapper中对应的parameterType应赋值为(其中#{}种的取值应和Map中的键名是一致的):
<select id="getPartInfoByUser" parameterType="java.util.Map" resultType="com.mybatis.entity.PartInfo"> SELECT * FROM tbInfoPart WHERE PartCode = #{partCode} AND PartName LIKE '%'+#{partName}+'%' AND SalePrice <![CDATA[>=]]> #{salePriceLow} AND SalePrice <![CDATA[<=]]> #{salePriceHigh} </select>
此种传参方式优点在于易扩展。