# SQL 传参

## SQL 传入单个参数

假设需要我们不需要 select \* 筛选出所有数据，而是根据 goodsId 精确的选出某一条数据，那么则需要在 SQL 语句中传入一个参数。

### 编写 select 语句

在 MyBatis\src\main\resources\mappers\goods.xml 文件 下的 \<mapper namespace="goods" >标签下添加下面标签。可以看到与 \<selectAll>  标签相比多了一个 parameterType 参数， 这立需要填参数类型，随后这个参数会被传到下面 select 语句的 #{value} 中。

```xml
    <select id="selectById" parameterType="Integer" resultType="indi.chester.mybatis.entity.Goods">
        select * from  t_goods WHERE goods_id=#{value }
    </select
```

### sqlSession 调用 select 语句

在 MyBatis\src\test\java\MyBatisTest.java 添加下面这个方法。这里用到了sqlSession.selectOne 方法，传入select 语句的位置 和 参数， 返回一个 Goods 对象。

```java
    @Test
    public void testSelectById() throws Exception{
        SqlSession sqlSession=null;
        try {
            sqlSession=MyBatisUtils.openSession();
            Goods good=sqlSession.selectOne("goods.selectById",1000);
            System.out.println(good.getTitle());
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            MyBatisUtils.closeSession(sqlSession);
        }
    j
```

运行结果:&#x20;

```
十月妈咪孕妇护肤品4件套 水润修护专用孕妇化妆品套装
```

## SQL 传入多个参数

假设我们需要选取一定价格范围内的商品，那么只传一个参数是不行的，至少要传入两个参数。这时需要将 parameterType 设置为 java.util.Map, 将参数名用字典的键表示，参数值用字典的值表示。

在 MyBatis\src\main\resources\mappers\goods.xml 文件 下的 \<mapper namespace="goods" >标签下添加下面标签：

```xml
    <select id="selectByPriceRange" parameterType="java.util.Map" resultType="indi.chester.mybatis.entity.Goods">
        select * from  t_goods WHERE current_price BETWEEN  #{min} and #{max}
        ORDER BY current_price  LIMIT 0, #{limit}
    </select>
```

这里我们传入了三个参数，min, max 和 limit, 在 传入的 Map 中需要存有以这三个参数名为键的键值对。

在 MyBatis\src\test\java\MyBatisTest.java 添加下面这个方法。这里用到了sqlSession.selectList 方法，传入select 语句的位置 和 参数， 返回一个 Goods 对象。参数是一个HashMap, SQL语句需要的参数都位于 HashMap 对象中的键值对。

```java
    @Test
    public void testSelectByPriceRange() throws Exception{
        SqlSession sqlSession=null;
        try {
            sqlSession=MyBatisUtils.openSession();
            HashMap<String, Integer> parmsMap=new HashMap<String, Integer>();
            parmsMap.put("min",100);
            parmsMap.put("max",500);
            parmsMap.put("limit",10);
            List<Goods> goodsList=sqlSession.selectList("goods.selectByPriceRange",parmsMap);
            for (Goods g: goodsList){
                System.out.println(g.getTitle());
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            MyBatisUtils.closeSession(sqlSession);
        }
    }
```

运行结果:

```
MeadJohnson 美赞臣 安婴儿A+奶粉 1段 400克盒装 婴儿配方奶粉
MeadJohnson 美赞臣 安婴儿A+奶粉 1段 400克盒装 婴儿配方奶粉
MeadJohnson 美赞臣 安婴儿A+奶粉 1段 400克盒装 婴儿配方奶粉
美康粉黛 孕期彩妆睛彩出色眼部彩妆3件套妈咪电眼炼成记 眉笔+眼线笔+睫毛膏 眉笔暖咖
【日本】尤尼佳Moony纸尿裤M64*1包
【日本】MOONY NB90纸尿裤*1包
【日本】尤妮佳Moony 纸尿裤L54枚*1包
子初 孕妇化妆品植物气垫BB霜 （滋润型/自然色）13g*2
亲润孕妇护肤品深层清洁豆乳备长炭黑面膜21片装
子初 孕妇护肤品洗浴套装（檀香木沐浴液540ml+檀香木洗发液540ml）
```

## 多表关联查询

假设有这么一个需求，查询 tgoods 中的前10条数据，并且将每一个商品的种类也得查询出来。由于返回类型多了一个商品种类，而商品种类位于 t\_category 中，所以返回类型不能再用 Goods 对象存储了，而是得用一个 Map 存储，键为字段名，值为数据。

在 MyBatis\src\main\resources\mappers\goods.xml 文件 下的 \<mapper namespace="goods" >标签下添加下面标签：

```xml
    <!--  利用 LinkedHashMap 保存多表关联结果, 键为字段名, 值为数值-->
    <select id="selectGoodsMap"  resultType="java.util.LinkedHashMap" >
        select g.*, c.category_name FROM t_goods g, t_category c
        WHERE g.category_id = c.category_id LIMIT 10
    </select>
```

&#x20;这里使用 LinkedHashMap 是为了查询出来的结果的字段与 数据表中的字段顺序保持一致。LinkedHashMap 可以看作是可以记录插入的键值对顺序的一个 HashMap。

在 MyBatis\src\test\java\MyBatisTest.java 添加下面这个方法：

```java
    @Test
    public void testSelectGoodsMap() throws Exception{
        SqlSession sqlSession=null;
        try {
            sqlSession=MyBatisUtils.openSession();
            List<Map> goodsListMap=sqlSession.selectList("goods.selectGoodsMap");
            for (Map map: goodsListMap){
                System.out.println(map);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            MyBatisUtils.closeSession(sqlSession);
        }
    }

```

运行结果:

```
{goods_id=739, title=亲润 孕妇护肤品豆乳大米盈润保湿胶原蚕丝面膜（18片装）, sub_title=卓效对抗孕期干燥，15分钟快速补水，补充胶原蛋白，幼滑肌肤。天然豆乳配方，温和低敏，孕产期、所有肤质适用。, original_cost=198.0, current_price=88.0, discount=0.444444, is_free_delivery=1, category_id=43, category_name=米粉}
{goods_id=740, title=爱恩幼 孕妇护肤品润养颜睡眠面膜 100g, sub_title=免洗配方，质地清透不黏腻，睡眠间为肌肤持续补充营养，并牢牢锁住水分，清晨醒来后，肌肤水润柔嫩，洋溢青春活力。, original_cost=96.0, current_price=49.0, discount=0.510417, is_free_delivery=1, category_id=44, category_name=牙胶/咬咬乐}
{goods_id=741, title=斯利安 孕妈专用 洗发水 氨基酸表面活性剂 舒缓头皮 滋养发根 让你的秀发会喝水 品质孕妈, sub_title=含叶酸 无硅油 深层锁水 天然成分 用心呵护您的秀发 让秀发 会喝水, original_cost=138.0, current_price=79.9, discount=0.578986, is_free_delivery=1, category_id=45, category_name=腰凳}
{goods_id=742, title=亲恩 孕妇护肤品 燕窝补水保湿6件套 孕期安全温和 补水保湿套装, sub_title=【买一送11，价值129元大礼包】萃取燕窝精华天然温和，深层补水，缓解孕期干燥，暗黄肌肤，水润修颜美肌，全套呵护肌肤，方便省心, original_cost=748.0, current_price=128.0, discount=0.171123, is_free_delivery=1, category_id=46, category_name=雨伞}
{goods_id=743, title=优美孕 补水保湿 黄金果水润嫩肤三件套(中样装 洁面乳50g 水50ml 乳液50ml), sub_title=孕妇护肤品，黄金果三件套（中样装），秉承天然护肤理念，萃取新西兰黄金果提取精华，针对孕期肤质而研制，补水保湿，减少色素沉着提亮肤色！给予您孕期肤质更细致更专业的呵护！, original_cost=319.0, current_price=39.0, discount=0.122257, is_free_delivery=1, category_id=47, category_name=手口湿巾}
{goods_id=744, title=雅滋美特 孕妇护肤品天然叶酸补水保湿三件化妆品套装, sub_title=提取天然叶酸，为孕期肌肤补充所需营养，补水保湿、滋润皮肤，令肌肤由内而外散发动人光彩。, original_cost=417.0, current_price=78.0, discount=0.18705, is_free_delivery=1, category_id=48, category_name=学步带}
{goods_id=745, title=美康粉黛 金风玉露隔离霜孕妇护肤品化妆品隔离污染均匀肤色持久服帖 自然无妆感 温情绿, sub_title=天然植物彩妆，孕妈妆前乳隔离霜，隔离污染 均匀肤色持久服帖，自然无妆感, original_cost=158.0, current_price=49.0, discount=0.310127, is_free_delivery=1, category_id=49, category_name=口水巾}
{goods_id=746, title=亲润 孕妇专用遮瑕保湿隔离提亮肤色气垫CC霜, sub_title=美颜小魔盒，3秒贴妆，8小时定妆，隔离修颜，1步打造好脸色。进口气垫粉扑，上妆非常服帖。, original_cost=198.0, current_price=128.0, discount=0.646465, is_free_delivery=1, category_id=50, category_name=安抚牙胶}
{goods_id=747, title=柔色孕期彩妆 植物彩妆买1送1 雾面口红唇膏不脱妆多色可选, sub_title=买1送1（送润唇膏1支，赠品不累计） 植物彩妆，孕妇儿童可用，雾面哑光，不脱妆不掉色口红，多色可选, original_cost=128.0, current_price=39.0, discount=0.304688, is_free_delivery=1, category_id=51, category_name=防丢失手环}
{goods_id=748, title=哇爱 孕妇待产专用待产包 13件套【实用型】, sub_title=哇爱实用型待产包，甄选优质材料，无尘环境操作，医用全棉，柔软舒适，哺乳透气干爽，专注孕妈用品安全，产妇入院待产推荐。, original_cost=158.0, current_price=49.9, discount=0.315823, is_free_delivery=1, category_id=52, category_name=纸尿裤}
```

### ResultMap 结果映射

重复上面的需求，假设我们希望把查询结果保存到一个 Java 对象，应该怎么办？

#### 新建 dto 对象

在  MyBatis\src\main\java\indi\chester\mybatis\dto 下 新建 GoodsDTO.java。 dto 表示 data transfer object, 也就是我们希望把 SQL 查询语句的结果储存到这个类对象中。&#x20;

```java
package indi.chester.mybatis.dto;

import indi.chester.mybatis.entity.Goods;

public class GoodsDTO {
    private Goods goods=new Goods() ;
    private String categoryName;

    public Goods getGoods() {
        return goods;
    }

    public String getCategoryName() {
        return categoryName;
    }
}

```

#### 创建 resultMap 映射

在 MyBatis\src\main\resources\mappers\goods.xml 中添加以下两个标签，用来查询数据表，且将返回结果和 java 对象利用 resultMap 关联起来。其中 \<resultMap> 标签中指明了 数据表中的字段名和 java 对象中的成员属性如何一一对应。特别的是 \<id> 标签必须存在，且必须为数据表的主键。

```xml
    <resultMap id="rmGoods" type="indi.chester.mybatis.dto.GoodsDTO">
        <id property="goods.goodsId" column="goods_id"></id>
        <result property="goods.title" column="title"></result>
        <result property="goods.originalCost" column="original_cost"></result>
        <result property="goods.currentPrice" column="current_price"></result>
        <result property="goods.discount" column="discount"></result>
        <result property="goods.isFreeDelivery" column="is_free_delivery"></result>
        <result property="goods.categoryId" column="category_id"></result>
        <result property="categoryName" column="category_name"></result>
    </resultMap>

    <select id="selectGoodsDTO"  resultMap="rmGoods">
        select g.*, c.category_name FROM babytun.t_goods g, babytun.t_category c
        WHERE g.category_id = c.category_id LIMIT 10
    </select>
```

#### sqlSession 调用 select 语句

在 MyBatis\src\test\java\MyBatisTest.java 添加下面这个方法:&#x20;

```java
   @Test
    public void testSelectGoodsDTO() throws Exception{
        SqlSession sqlSession=null;
        try {
            sqlSession=MyBatisUtils.openSession();
            List<GoodsDTO> goodsDTOList=sqlSession.selectList("goods.selectGoodsDTO");
            for (GoodsDTO g : goodsDTOList){
                System.out.println("{ title="+g.getGoods().getTitle() + ", category_name="+g.getCategoryName()+" }");
            }
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            MyBatisUtils.closeSession(sqlSession);
        }
    }
```

运行结果:&#x20;

```
{ title=亲润 孕妇护肤品豆乳大米盈润保湿胶原蚕丝面膜（18片装）, category_name=米粉 }
{ title=爱恩幼 孕妇护肤品润养颜睡眠面膜 100g, category_name=牙胶/咬咬乐 }
{ title=斯利安 孕妈专用 洗发水 氨基酸表面活性剂 舒缓头皮 滋养发根 让你的秀发会喝水 品质孕妈, category_name=腰凳 }
{ title=亲恩 孕妇护肤品 燕窝补水保湿6件套 孕期安全温和 补水保湿套装, category_name=雨伞 }
{ title=优美孕 补水保湿 黄金果水润嫩肤三件套(中样装 洁面乳50g 水50ml 乳液50ml), category_name=手口湿巾 }
{ title=雅滋美特 孕妇护肤品天然叶酸补水保湿三件化妆品套装, category_name=学步带 }
{ title=美康粉黛 金风玉露隔离霜孕妇护肤品化妆品隔离污染均匀肤色持久服帖 自然无妆感 温情绿, category_name=口水巾 }
{ title=亲润 孕妇专用遮瑕保湿隔离提亮肤色气垫CC霜, category_name=安抚牙胶 }
{ title=柔色孕期彩妆 植物彩妆买1送1 雾面口红唇膏不脱妆多色可选, category_name=防丢失手环 }
{ title=哇爱 孕妇待产专用待产包 13件套【实用型】, category_name=纸尿裤 }
```
