Bootstrap

08 MyBatis之查询专题(返回对象/Map/List封装Map/Map封装Map)+列名与属性名映射的三种方法

准备:

INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (165, '6666', '丰田霸道', 32.00, '2020-11-11', '燃油车');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (166, '1202', '大众速腾', 30.00, '2020-11-11', '燃油车');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (167, '1203', '奔驰GLC', 5.00, '2010-12-03', '燃油车');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (168, '1204', '奥迪Q7', 3.00, '2009-10-11', '燃油车');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (169, '1205', '朗逸', 4.00, '2001-10-11', '新能源');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (171, '1207', '奥迪A6', 30.00, '2000-01-02', '燃油车');
INSERT INTO `t_car` (`id`, `car_num`, `brand`, `guide_price`, `produce_time`, `car_type`) VALUES (172, '6666', '丰田霸道', 32.00, '2020-11-11', '燃油车');

1. 返回一个对象

需求 : 查询的结果,有对应的实体类,并且查询结果只有一条

1.1 用对象接收返回值

package com.sunsplanter.mybatis.mapper;

public interface CarMapper {
    Car selectById(Long id);
}
<?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.sunsplanter.mybatis.mapper.CarMapper">
    <select id="selectById" resultType="Car">
        select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car where id = #{id}
    </select>
</mapper>
package com.sunsplanter.mybatis.test;

public class CarMapperTest {

    @Test
    public void testSelectById(){
        CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
        Car car = mapper.selectById(35L);
        System.out.println(car);
    }
}

在这里插入图片描述

1.2 用list接收返回值

即使返回结果只有一条(一个对象), 仍能用list接收, 但是在将来输出的时候有些不同

//mapper接口新增方法
List<Car> selectByIdToList(Long id);
<select id="selectByIdToList" resultType="Car">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car where id = #{id}
</select>
@Test
public void testSelectByIdToList(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    List<Car> cars = mapper.selectByIdToList(35L);
    System.out.println(cars);
}

可以看到 , 返回的对象用方括号扩了起来
在这里插入图片描述

2. 返回多个对象

返回多个对象只能用list接收.

List<Car> selectAll();
<select id="selectAll" resultType="Car">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car
</select>
@Test
public void testSelectAll(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    List<Car> cars = mapper.selectAll();
    cars.forEach(car -> System.out.println(car));
}

在这里插入图片描述

3. 返回一个map

当返回的数据,没有合适的实体类对应的话,可以采用Map集合接收。字段名做key,字段值做value。

且如果可以保证只有一条数据,则返回一个Map集合即可。
在这里插入图片描述

Map<String, Object> selectByIdRetMap(Long id);
<!--此处的resultType指定为map-->
<select id="selectByIdRetMap" resultType="map">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car where id = #{id}
</select>
@Test
public void testSelectByIdRetMap(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    Map<String,Object> car = mapper.selectByIdRetMap(35L);
    System.out.println(car);
}

可以看到 , 输出的结果和用实体接收并输出是一样的.
在这里插入图片描述

4. 返回多个map

需求: 返回多条数据, 且都没有对应的实体接收

4.1 第一种做法List

分析: 将每条数据存入一个map, 将所有map一起存入list
在这里插入图片描述

List<Map<String,Object>> selectAllRetListMap();
<select id="selectAllRetListMap" resultType="map">
  select id,car_num carNum,brand,guide_price guidePrice,produce_time produceTime,car_type carType from t_car
</select>
@Test
public void testSelectAllRetListMap(){
    CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    List<Map<String,Object>> cars = mapper.selectAllRetListMap();
    System.out.println(cars);
}

执行结果

//方括号包裹
[
  {carType=燃油车, carNum=103, guidePrice=50.30, produceTime=2020-10-01, id=33, brand=奔驰E300L}, 
  {carType=电车, carNum=102, guidePrice=30.23, produceTime=2018-09-10, id=34, brand=比亚迪汉}, 
  {carType=燃油车, carNum=103, guidePrice=50.30, produceTime=2020-10-01, id=35, brand=奔驰E300L}, 
  {carType=燃油车, carNum=103, guidePrice=33.23, produceTime=2020-10-11, id=36, brand=奔驰C200},
  ......
]

4.2 第二种做法Map<String,Map>

分析:

大Map的键: 每条数据的id
大Map的值: 每条数据存入小Map

优势: 拿数据的id作为key, 将来可以比list更方便取出指定某条数据

在这里插入图片描述

//@MapKey注解指定, selectAllRetMap方法返回的map中,将id字段的值作为外层大Map的键
@MapKey("id")
Map<Long,Map<String,Object>> selectAllRetMap();
<select id="selectAllByMapUnderscoreToCamelCase" resultType="map">
  select * from t_car
</select>
@Test
public void testSelectAllByMapUnderscoreToCamelCase(){
    CarMapper carMapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);
    Map<Long, Map<String,object>> cars = carMapper.selectAllByMapUnderscoreToCamelCase();
    System.out.println(cars);
}

在这里插入图片描述

5. 列名与属性名映射的三种方法

按照开发规范, 大多数时候数据库的列名与实体字段属性名并不相同, 此时需要考虑怎么让系统正确绑定二者

● 第一种方式:as 给列起别名
● 第二种方式:使用resultMap进行结果映射
● 第三种方式:开启驼峰命名自动映射(配置settings)

5.1 as 给列起别名

这种方式虽然非常直观, 但是字段多起来后代码会复杂

<!--列名在前, 实体属性在后-->
<select id="listAllCars" resultType="car">
select 
	id,
	car_num as carNum
	from t_car
</select>

5. 使用resultMap进行结果映射

<!--
        resultMap:
            id:这个结果映射的标识,作为select标签的resultMap属性的值。
            type:结果集要映射的类。可以使用别名。
-->
<resultMap id="carResultMap" type="car">
  <!--对象的唯一标识,官方解释是:为了提高mybatis的性能。建议写上。-->
  <id property="id" column="id"/>
  <result property="carNum" column="car_num"/>
  <!--当属性名和数据库列名一致时,可以省略。但建议都写上。-->
  <!--javaType用来指定属性类型。jdbcType用来指定列类型。一般可以省略。-->
  <result property="brand" column="brand" javaType="string" jdbcType="VARCHAR"/>
  <result property="guidePrice" column="guide_price"/>
  <result property="produceTime" column="produce_time"/>
  <result property="carType" column="car_type"/>
</resultMap>

<!--resultMap属性的值必须和resultMap标签中id属性值一致。-->
<select id="selectAllByResultMap" resultMap="carResultMap">
  select * from t_car
</select>

5.3 自动驼峰映射

首先, 开启自动驼峰映射必须满足条件, 即
属性名遵循Java的命名规范,数据库表的列名遵循SQL的命名规范。

在这里插入图片描述

<!--放在properties标签后面-->
<settings>
  <setting name="mapUnderscoreToCamelCase" value="true"/>
  <setting name="autoMappingBehavior" value="FULL"/>
</settings>

在这里插入图片描述

;