单表查询

resultType与resultMap

  • pojo包下实体类User ```java package com.tedu.DbDemo.pojo;

public class User { Integer userId; String username; String password; //它们的set,get方法,不展示了,占位置 }

  1. - User表中,此时数据操作结果集user_id pojo包下实体类userId不一致,其它属性username,password一致
  2. - mapper包下接口UserMapper
  3. ```java
  4. package com.tedu.DbDemo.mapper;
  5. public interface UserMapper {
  6. public List<User> select1();
  7. public List<User> select2();
  8. }

<select id="select2" resultMap="map1">
    select user_id,username,password from user
</select>


- controller层UserController类
```java
package com.tedu.DbDemo.controller;

@RestController
public class UserController {
    @Autowired
    UserMapper userMapper;

    @RequestMapping("/select1")
    public List<User> select1(){
        return userMapper.select1();
    }

    @RequestMapping("/select2")
    public List<User> select2(){
        return userMapper.select2();
    }
}
  • 结论

    • select resultType要求结果集列名与类中的属性名一样
    • select resultMay 对结果集列名与类中的属性名不做要求,通过映射连接

      Mybatis关联关系

  • 只有两种association(一对一)、collection(一对多),表现很简洁

  • 逆向工程不能生成多表联查,只能手写

    多表查询,表与表之间一对一关系

  • 一个订单对应一个用户

  • pojo包下实体类订单表Order、用户表User ```java package com.tedu.DbDemo.pojo;

public class Order { Integer orderId; Integer total; User user; //注意还有一个 user属性,这是关键 //它们的set,get方法,不展示了,占位置 }


- mapper包下接口OrderMapper
```java
package com.tedu.DbDemo.mapper;

public interface OrderMapper {
    public Order selectById(Integer orderId);
}
  • mapper包下与接口对应的OrderMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.tedu.DbDemo.mapper.OrderMapper">
      <resultMap type="com.tedu.DbDemo.pojo.Order" id="map2">
          <result column="order_id" property="orderId"/>
          <result column="total" property="total"/>
          <!-- 结果集里面还要有user表的信息,映射到User类,采用标签association表示一对一
          property表示结果子集合的类型(表名),javaType表示它对应的实体类 -->
          <association property="user" javaType="com.tedu.DbDemo.pojo.User">
              <result column="user_id" property="userId"/>
              <result column="username" property="username"/>
          </association>
      </resultMap>
      <!-- select放的是sql语句
      #{}是占位符-->
      <select id="selectById" resultMap="map2" parameterType="Integer">
          SELECT 
          order_id,total,jt_order.user_id,username
          FROM jt_order ,USER 
          WHERE jt_order.order_id=#{orderId}
          AND user.user_id=jt_order.user_id
      </select>
    </mapper>
    
  • controller层OrderController类 ```java package com.tedu.DbDemo.controller;

@RestController public class OrderController { @Autowired OrderMapper orderMapper; @RequestMapping(“/selectOrderId”) public Order selectOneToOne() { Order order = orderMapper.selectById(1); return order; } }


- association标签、对象中含有一个对象属性  表示一对一

<a name="mcucy"></a>
### 多表查询,表与表之间多对多关系

- 一种商品分类对应多个商品
- pojo包下实体类商品分类表Category、商品表Item
```java
package com.tedu.DbDemo.pojo;

import java.util.List;

public class Category {
    Integer categoryId;
    String categoryName;

    List<Item> itemList;
    //注意还有一个 List<Item>属性,集合这是关键
    //它们的set,get方法,不展示了,占位置
}
  • mapper包下接口CategoryMapper ```java package com.tedu.DbDemo.mapper;

public interface CategoryMapper { public Category selectById(Integer categoryId); }


- mapper包下与接口对应的CategoryMapper.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tedu.DbDemo.mapper.CategoryMapper">
    <resultMap type="com.tedu.DbDemo.pojo.Category" id="map1">
        <result column="category_Id" property="categoryId"/>
        <result column="category_Name" property="categoryName"/>
        <!--一对一用assiocation 一对多是collection 
            collection里面 property是集合的名字,ofType是集合每个数据的接口.类名
         -->
        <collection property="itemList" ofType="com.tedu.DbDemo.pojo.Item">
            <result column="item_name" property="itemName"/>
        </collection>
    </resultMap>
    <!-- 
    resultType 单表
    resultMap 多表
    parameterType  参数简单
    paremeterMap   参数复杂
     -->
    <select id="selectById" resultMap="map1" parameterType="Integer">
        SELECT category.category_id,category_name,item_name
        FROM category,item
        WHERE category.category_id=#{categoryId}
        AND item.category_id=category.category_id
    </select>
</mapper>
  • 注意这里的sql语句,加入参数用#{},#{}封装了jdbc的PreparedStatement,能有效的防治sql注入问题,工作中也不用${},用#{}
  • controller层CategoryController类 ```java package com.tedu.DbDemo.controller;

@RestController public class CategoryController {

@Autowired
CategoryMapper categoryMapper;
@RequestMapping("/category")
public Category selectOneToAll() {
    Category category = categoryMapper.selectById(1);
    return category;
}

}


- collection标签,对象中有一个对象集合属性,表示 一对多

<a name="TZbhu"></a>
## 高级查询

1. 高级查询中的where  条件  and  like条件
1. in查询
- pojo包下实体类商品表Item
```java
package com.tedu.DbDemo.pojo;

public class Item {
    Integer itemId;
    String itemName;
    Integer categoryId;
    //它们的set,get方法,不展示了,占位置
}
  • mapper包下接口ItemMapper ```java package com.tedu.DbDemo.mapper;

public interface ItemMapper { //参数item中可以包含categoryId,itemName //如果item中的某个属性值不为空,就根据这个属性值查找,where and语句 public List select1(Item item);

//根据商品编号,in子查询
public List<Item> selectByList(List<Integer> list);

}


- mapper包下与接口对应的ItemMapper.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tedu.DbDemo.mapper.ItemMapper">
    <!-- list<Item> select1() 如果方法返回的是集合,resultType的值是集合中元素的数据类型
    parameterType是参数的类型
     参数item中有categroryId,itemName属性 -->
    <select id="select1" resultType="com.tedu.DbDemo.pojo.Item" parameterType="com.tedu.DbDemo.pojo.Item">
        SELECT category_id categoryId
        ,item_name itemName
        FROM item
        <!-- 当直接写where
        不传参数 生成的sql是from item where
        前面的参数不传 ,sql是from item where and item_name like,出现错误
        解决方法是把where改成标签<where>
         -->
        <where>
            <if test="categoryId != null">
                <!-- category_id是列名 , categoryId是传入参数item中的属性 -->
                category_id=#{categoryId}
            </if>
            <if test="itemName != null">
                <!-- concat是mysql内置的函数,拼接字符串 -->
                and item_name like concat('%',#{itemName},'%')
            </if>
        </where>
    </select>
    <!-- 这里给列名设置了别名,列名和属性名相同,不再需要用resultMap映射 -->
    <select id="selectByList" resultType="com.tedu.DbDemo.pojo.Item" parameterType="Integer">
        SELECT item_id itemId,
        category_id categoryId,
        item_name itemName
        FROM item
        WHERE item_id IN 

        <!-- foreach 遍历集合 collection指定集合名称
        item指定从集合取出的数据放在 id 中,id就是for循环的 i 
        open separator close的值就是in查询中的 (     ,  ,    ,    )
        -->
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
</mapper>
  • controller层ItemController类 ```java package com.tedu.DbDemo.controller;

@RestController public class ItemController { @Autowired ItemMapper itemMapper;

//模拟高级搜索中多个条件
//where and  like查询
@RequestMapping("/item/Where")
public List<Item> selectWhere(Item item){
    List<Item> listList = itemMapper.select1(item);
    return listList;
}
//模拟用户的复选框选中多个值
//in查询
@RequestMapping("/item/selectIn")
public List<Item> selectIn(){
    //模拟用户输入复选框 第 2,3,4 个
    List<Integer> list = new ArrayList<Integer>();
    list.add(2);
    list.add(3);
    list.add(4);
    List<Item> itemList = itemMapper.selectByList(list);
    return itemList;
}

}

<a name="E0EAl"></a>
## 扩展
<a name="6DvY5"></a>
### <sql><include>

- 可以在配置文件中调用的地方都进行include引用
```xml
<sql id="cols">id,name,birthday,address</sql>
  • refid引用上面的sql语句

    <select id="list" resultType="user">
     select <include refid="cols"/> from user
    </select>
    

    SQL中有特殊字符

  • 当SQL中有特殊字符,mybatis不能正常解析时,用CDATA括起来就解决了

  • 如 <=不能正常解析:

    <![CDATA[
       and age<=#{age}
    ]]>
    

    总结

  • 首先根据业务需求写出sql语句,sql语句告诉你需要用到哪些表,哪些实体类

  • 建立controller、mapper、pojo包
  • pojo包下建立实体类
  • 根据业务设定mapper包下接口
  • 与接口对应的xml
    • namespace为xml对应的 包名.类名
    • 列名与实体类属性相等,直接用resultType作为返回类型,否则需要用resultMap将列名和实体类属性映射
      • 返回值类型为 包名.类名
  • 配置application.yml
    • 两处填写的地址都是接口的包名
  • 包扫描注解@mapperScan(“接口包名”)
    • 告诉框架给这个变量一个对象
  • 执行对像方法后,首先是找到接口方法
  • 每个接口都对应一个同名的xml,xml中的namespace的值是接口的包名.类名,sql语句的id和接口方法名相同,执行接口方法,就会执行方法名对应id的sql语句。
    • mapper.xml中定义的每个sql 的parameterType的类型和Mapper接口方法的输入参数类型一样
    • 当数据库操作的结果集与实体类的属性名相同时,mapper.xml中使用resultType作为结果集的类型,且resultType的类型和Mapper接口方法的输出参数类型和一样,不相同或者多表时时,用resultMap映射,让结果集和实体类连在一起
  • 最后以实体类的形式返回,框架调用jackson框架将对象转换为json返回