0%

Mybatis查询语句专题

  • Mybatis查询语句专题
    • 返回Car
    • 返回List<Car>
    • 返回Map
    • 返回List<Map>
    • 查询结果列名和java对象属性名映射

十一、★★★Mybatis查询语句专题

  • 准备工作:
    • 模块名:mybatis-008-select
    • 打包方式:jar
    • 引入依赖:mysql驱动依赖、mybatis依赖、logback依赖、junit依赖。
    • 引入配置文件:jdbc.propertiesmybatis-config.xmllogback.xml
    • 创建 pojo 类:Car
    • 创建 Mapper 接口:com.f.mybatis.mapper.CarMapper
    • 创建 Mapper 接口对应的映射文件:com/f/mybatis/mapper/CarMapper.xml
    • 创建单元测试:CarMapperTest
    • 创建工具类:SqlSessionUtil

11.1 返回Car

  • 当查询的结果,有对应的实体类,并且查询结果只有一条时:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.f.mybatis.mapper;

    import com.f.mybatis.pojo.Car;

    /**
    * @author fzy
    * @date 2024/1/10 15:29
    */
    public interface CarMapper {
    Car selectById(Long id);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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.f.mybatis.mapper.CarMapper">
    <select id="selectById" resultType="Car">
    SELECT id,
    car_num AS carNum,
    brand,
    guide_price AS guidePrice,
    produce_time AS produceTime,
    car_type AS carType
    FROM t_car
    WHERE id = #{id}
    </select>
    </mapper>
    1
    2
    3
    4
    5
    6
    7
    8
    @Test
    public void testSelectById() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Car car = mapper.selectById(2L);
    System.out.println(car);
    SqlSessionUtil.close(sqlSession);
    }
  • 思考:如果查询结果是一条的话可以使用 List 集合接收吗?

    当然可以,只不过该 List 集合中只有一个 Car 对象而已。

    • 反过来,如果查询结果不是一条记录,是多条记录的话,只采用单个实体类对象接收,这样就会出现下面的异常:TooManyResultsException

11.2 返回List<Car>

  • 当查询的记录条数是多条的时候,必须使用集合接收。如果使用单个实体类接收会出现异常。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package com.f.mybatis.mapper;

    import com.f.mybatis.pojo.Car;

    import java.util.List;

    /**
    * @author fzy
    * @date 2024/1/10 15:29
    */
    public interface CarMapper {
    List<Car> selectAll();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?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.f.mybatis.mapper.CarMapper">
    <select id="selectAll" resultType="Car">
    SELECT id,
    car_num AS carNum,
    brand,
    guide_price AS guidePrice,
    produce_time AS produceTime,
    car_type AS carType
    FROM t_car
    </select>
    </mapper>
    1
    2
    3
    4
    5
    6
    7
    8
    @Test
    public void testSelectAll() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Car> cars = mapper.selectAll();
    cars.forEach(car -> System.out.println(car));
    SqlSessionUtil.close(sqlSession);
    }

11.3 返回Map

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

    如果可以保证查询结果只有一条数据,则返回一个 Map 集合即可。

    ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/Java-SSM-notebook/img/Mybatis/返回Map.png)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.f.mybatis.mapper;

    import com.f.mybatis.pojo.Car;

    import java.util.List;
    import java.util.Map;

    /**
    * @author fzy
    * @date 2024/1/10 15:29
    */
    public interface CarMapper {
    Map<String, Object> selectByIdReturnMap(Long id);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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.f.mybatis.mapper.CarMapper">
    <select id="selectByIdReturnMap" resultType="map">
    SELECT id,
    car_num AS carNum,
    brand,
    guide_price AS guidePrice,
    produce_time AS produceTime,
    car_type AS carType
    FROM t_car
    WHERE id = #{id}
    </select>
    </mapper>

    **resultType 的完整类名应该是 java.util.Map,但是在 mybatis 框架内部内建了很多别名,java.util.Map 的别名就是 map,所以可以直接使用 resultType="map"**。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Test
    public void testSelectByIdReturnMap() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Map<String, Object> result = mapper.selectByIdReturnMap(2L);
    for (Map.Entry<String, Object> entry : result.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
    }
    SqlSessionUtil.close(sqlSession);
    }
  • 思考:如果返回一个 Map 集合,那么可以将这个 Map 集合放到 List 集合中吗?

    当然可以。

    • 反过来,如果返回的不是一条记录,是多条记录的话,只采用单个 Map 集合接收,这样同样会出现之前的异常:TooManyResultsException

11.4 返回List<Map>

  • 如果查询结果条数大于等于 1 条数据,则可以返回一个存储 Map 集合的 List 集合。List<Map> 类似于 List<Car>

    ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/Java-SSM-notebook/img/Mybatis/返回MapList.png)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.f.mybatis.mapper;

    import com.f.mybatis.pojo.Car;

    import java.util.List;
    import java.util.Map;

    /**
    * @author fzy
    * @date 2024/1/10 15:29
    */
    public interface CarMapper {
    List<Map<String, Object>> selectAllReturnListMap();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?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.f.mybatis.mapper.CarMapper">
    <select id="selectAllReturnListMap" resultType="map">
    SELECT id,
    car_num AS carNum,
    brand,
    guide_price AS guidePrice,
    produce_time AS produceTime,
    car_type AS carType
    FROM t_car
    </select>
    </mapper>

    resultType 还是 map

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Test
    public void testSelectAllReturnListMap() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Map<String, Object>> results = mapper.selectAllReturnListMap();
    results.forEach(result -> {
    for (Map.Entry<String, Object> entry : result.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
    }
    System.out.println("==========");
    });
    SqlSessionUtil.close(sqlSession);
    }

返回Map<String, Map>

  • 对于 11.4 小节返回的 List<<Map>,取数据时比较麻烦,为了能快速取出想要的 Map 集合,可以用 Caridkey,对应的 Map 集合做 value

    ![](../../../../../Running Noob/计算机/Typora笔记/笔记-git仓库/Java-SSM-notebook/img/Mybatis/返回大Map.png)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package com.f.mybatis.mapper;

    import com.f.mybatis.pojo.Car;
    import org.apache.ibatis.annotations.MapKey;

    import java.util.List;
    import java.util.Map;

    /**
    * @author fzy
    * @date 2024/1/10 15:29
    */
    public interface CarMapper {
    /**
    * 查询所有的Car,返回一个大Map集合
    * 大Map集合的key是每条记录的主键值
    * 大Map集合的value是每条记录的数据
    * @return
    */
    @MapKey("id") // 将查询结果的id值作为整个大Map集合的key
    Map<Long, Map<String, Object>> selectAllReturnBigMap();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?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.f.mybatis.mapper.CarMapper">
    <select id="selectAllReturnBigMap" resultType="map">
    SELECT id,
    car_num AS carNum,
    brand,
    guide_price AS guidePrice,
    produce_time AS produceTime,
    car_type AS carType
    FROM t_car
    </select>
    </mapper>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Test
    public void testSelectAllReturnBigMap() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    // 返回的大Map
    Map<Long, Map<String, Object>> results = mapper.selectAllReturnBigMap();
    /**
    * {
    * 2={carType=混动, carNum=1111, guidePrice=100.00, produceTime=2023-10-12, id=2, brand=劳斯莱斯},
    * 4={carType=新能源, carNum=1003, guidePrice=40.00, produceTime=2022-10-12, id=4, brand=问界}
    * }
    */
    System.out.println(results);
    SqlSessionUtil.close(sqlSession);
    }

11.5 ★查询结果列名和java对象属性名映射

  • 查询结果的列名和 java 对象的属性名对应不上怎么办?

    • 例如列名为 car_num,java 对象属性名为 carNum
      • 这是很正常的,因为在 mysql 中,字段命名用 _ 进行分割;而在 java 中,属性命名用小驼峰命名方式。
    • 一但查询结果列名和 java 对象的属性名对应不上,就会出现 java 对象的相应属性无法赋值的问题,相应属性就会为 null。
  • 有三种方式可以解决这个问题:

    • 第一种方式:在 SQL 语句中使用 as 给列起别名。

    • 第二种方式:在 SqlMapper.xml 文件中使用 resultMap 标签进行结果映射。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      package com.f.mybatis.mapper;

      import com.f.mybatis.pojo.Car;
      import org.apache.ibatis.annotations.MapKey;

      import java.util.List;
      import java.util.Map;

      /**
      * @author fzy
      * @date 2024/1/10 15:29
      */
      public interface CarMapper {
      /**
      * 查询所有Car的信息,使用resultMap标签进行结果映射
      *
      * @return
      */
      List<Car> selectAllByResultMap();
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      <?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.f.mybatis.mapper.CarMapper">
      <!-- 专门定义一个结果映射,在这个结果映射当中指定数据库表的字段名和Java类的属性名的对应关系 -->
      <!--
      1.type属性:用来指定POJO类的类名,全限定名称应该是com.f.mybatis.pojo.Car,
      但是因为在mybatis-config.xml中设置了typeAliases中的包名,所以可以直接用Car(不区分大小写)
      2.id属性:指定resultMap的唯一标识,这个id将来要在select标签中使用
      -->
      <resultMap id="carResultMap" type="Car">
      <!-- 如果数据库表中有主键,建议这里配置一个id标签,
      这样的配置可以让mybatis提高效率-->
      <id property="id" column="id"/>
      <!-- property后面填写POJO类的属性名 -->
      <!-- column后面填写数据库表的字段名 -->
      <result property="carNum" column="car_num"/>
      <!-- <result property="brand" column="brand"/>
      如果property和column的名字一样,就可以省略-->
      <result property="guidePrice" column="guide_price"/>
      <result property="produceTime" column="produce_time"/>
      <result property="carType" column="car_type"/>
      </resultMap>
      <!-- select标签的resultMap属性,用来指定使用哪个结果映射。
      resultMap后面的值是定义的resultMap的id -->
      <select id="selectAllByResultMap" resultMap="carResultMap">
      SELECT * FROM t_car
      </select>
      </mapper>
      1
      2
      3
      4
      5
      6
      7
      8
      @Test
      public void testSelectAllByResultMap() {
      SqlSession sqlSession = SqlSessionUtil.openSession();
      CarMapper mapper = sqlSession.getMapper(CarMapper.class);
      List<Car> cars = mapper.selectAllByResultMap();
      cars.forEach(car -> System.out.println(car));
      SqlSessionUtil.close(sqlSession);
      }
    • 第三种方式:在 mybatis-config.xml 文件中配置开启”驼峰命名自动映射”。

      • 使用这种方式的前提是:属性名遵循 Java 的命名规范,数据库表的列名遵循 SQL 的命名规范

        • Java 命名规范:首字母小写,后面每个单词首字母大写,遵循小驼峰命名方式。
        • SQL命名规范:全部小写,单词之间采用下划线分割。

        例如:

        实体类中的属性名数据库表的列名
        carNumcar_num
        carTypecar_type
        produceTimeproduce_time
      • 如果要启用该功能,需要在 mybatis-config.xml 文件中进行配置:

        1
        2
        3
        4
        <!--放在properties标签后面-->
        <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        </settings>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      package com.f.mybatis.mapper;

      import com.f.mybatis.pojo.Car;
      import org.apache.ibatis.annotations.MapKey;

      import java.util.List;
      import java.util.Map;

      /**
      * @author fzy
      * @date 2024/1/10 15:29
      */
      public interface CarMapper {
      /**
      * 查询所有Car的信息,但是启用了驼峰命名自动映射机制
      *
      * @return
      */
      List<Car> selectAllByMapUnderscoreToCamelCase();
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?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.f.mybatis.mapper.CarMapper">
      <select id="selectAllByMapUnderscoreToCamelCase" resultType="Car">
      SELECT * FROM t_car
      </select>
      </mapper>
      1
      2
      3
      4
      5
      6
      7
      8
      @Test
      public void testSelectAllByMapUnderscoreToCamelCase() {
      SqlSession sqlSession = SqlSessionUtil.openSession();
      CarMapper mapper = sqlSession.getMapper(CarMapper.class);
      List<Car> cars = mapper.selectAllByMapUnderscoreToCamelCase();
      cars.forEach(car -> System.out.println(car));
      SqlSessionUtil.close(sqlSession);
      }
---------------The End---------------