MyBatis中ResultMap的元素使用解析

ResultMap中鉴别器说明

在查询结果中,有时候一个数据库的查询结果会返回多个不同的结果集(总结上是有一定联系的)。discriminator成为鉴别器,类似于java语句中的switch语句,正是用于处理这种情况。并且,discriminator还能够处理包含继承层次的结果映射。

ResultMap中鉴别器使用实例

之前的一篇文章中,根据MyBatis官方给出的代码示例,尝试构建数据表和类结构完成了示例中较为复杂的一个ResultMap的使用实例,具体见: MyBatis中ResultMap使用实例解析。这里同样根据如下的MyBatis官方文档给出的示例,来说明resultMap中discriminator的使用。MyBatis官方文档中在对dircriminator进行说明的时候,使用了如下的示例:

根据上述的配置代码,在对查询结果进行映射的过程中,会根据vehicle_type查询列的结果,使用case元素进行对应。例如,当vehicle_type=1时,则将结果映射为carResult(这里应该是Car类的定义的别名)对象,而Car为Vehicle的子类,具有额外的一个doorCount属性,因此此时查询结果集映射后得到的对象实例应该是Car类的对象。不仅包含Vehicle中的基础属性,还包含额外的doorCount属性。同样的,当vehicle_type分别等于2,3,4时,则会分别映射为Vehicle子类的Truck,Van和Suv类的对象。而当vehicle_type不对应于case中定义的各个值时,将会映射为外层的Vehcile父类对象。这就是discriminator(鉴别器)的作用。

创建相应的父类和子类结构和表结构

根据上述的示例分析,现在实现该实例。首先将其中的属性进行了改变,然后定义了父类Vehicle和相应的子类Car,Truck和Suv如下:

@Data
public class Vehicle {
    private Integer id; // id
    private String brand;
    private String color;
    private Date productDate;
    private Integer vehicleType;
}

@Data
public class Car extends Vehicle {
    private Integer doorCount;
}

@Data
public class Suv extends Vehicle {
    private Boolean allWheelDriver;
}

@Data
public class Truck extends Vehicle {
    private Integer boxSize;
    private String capacity;
}

创建对应的tb_vehicle表结构并插入相应的数据:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_vehicle
-- ----------------------------
DROP TABLE IF EXISTS `tb_vehicle`;
CREATE TABLE `tb_vehicle` (
  `id` int(11) NOT NULL,
  `brand` varchar(255) DEFAULT NULL,
  `color` varchar(255) DEFAULT NULL,
  `product_date` datetime DEFAULT NULL,
  `vehicle_type` int(255) DEFAULT NULL,
  `door_count` int(255) DEFAULT NULL,
  `all_wheel_driver` tinyint(255) DEFAULT NULL,
  `box_size` int(11) DEFAULT NULL,
  `capacity` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of tb_vehicle
-- ----------------------------
BEGIN;
INSERT INTO `tb_vehicle` VALUES (1, 'BMW', 'red', '2020-02-02 00:00:00', 1, 4, 0, 2, '50');
INSERT INTO `tb_vehicle` VALUES (2, 'Maserati', 'blue', '2019-01-01 00:00:00', 2, 4, 0, 2, '80');
INSERT INTO `tb_vehicle` VALUES (3, 'Ford', 'black', '2020-02-12 00:00:00', 3, 2, 1, 4, '200');
INSERT INTO `tb_vehicle` VALUES (4, 'CAT', 'yellow', '2019-04-01 00:00:00', 0, 2, 1, 0, '1000');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;

插入的四条数据的vehicle_type分别为1,2,3,0,分别对应Car,Suv,Truck和Vehicle四个类的查询结果映射。

构造MyBatis结果映射

根据上述的表和类,构造SQL的查询语句和影响的结果映射ResultMap,vehicleMapper.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="cn.zyt.springbootlearning.dao.VehicleMapper">

    <resultMap id="vehicleMap" type="cn.zyt.springbootlearning.domain.mybatis.discriminator.Vehicle">
        <id property="id" column="id"/>
        <result property="brand" column="brand"/>
        <result property="color" column="color"/>
        <result property="productDate" column="product_date"/>
        <result property="vehicleType" column="vehicle_type"/>

        <discriminator javaType="int" column="vehicle_type">
            <case value="1" resultType="cn.zyt.springbootlearning.domain.mybatis.discriminator.Car">
                <result property="doorCount" column="door_count"/>
            </case>
            <case value="2" resultType="cn.zyt.springbootlearning.domain.mybatis.discriminator.Suv">
                <result property="allWheelDriver" column="all_wheel_driver"/>
            </case>
            <case value="3" resultType="cn.zyt.springbootlearning.domain.mybatis.discriminator.Truck">
                <result property="boxSize" column="box_size"/>
                <result property="capacity" column="capacity"/>
            </case>
        </discriminator>
    </resultMap>

</mapper>

这里可以看到使用了discriminator来进行结果的不同映射,使用vehicle_type字段来区分映射的关系。并针对不同的映射类型,设置相应包含的映射字段。下面编写VehicleMapper.java映射接口文件:

@Repository
public interface VehicleMapper {

    @Select("select * from tb_vehicle where id=#{id}")
    @ResultMap("vehicleMap")
    Vehicle getVehicle(Integer id);

    @Select("select * from tb_vehicle")
    @ResultMap("vehicleMap")
    List<Vehicle> getVehicleList();
}

然后编写简单的Controller来直接调用Mapper对象的getVehicleList方法获取查询结果,返回JSON数据结构:

从上述结果可以看到,同一个表中查询出来的4条数据,分别被映射为四个不同的类对象(从上述四条结果中包含不同的字段可以看出),分别对应Car,Suv,Truck和Vehicle,前三者在分别包含Vehicle中基本属性的同时,各自具有分别不同的属性值。

发布了296 篇原创文章 · 获赞 35 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/yitian_z/article/details/104208043
今日推荐