MyBatis 3手册 MyBatis 3 结果映射-鉴别器

2024-02-25 开发教程 MyBatis 3手册 匿名 3

鉴别器

<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>

有时候,一个数据库查询可能会返回多个不同的结果集(但总体上还是有一定的联系的)。 鉴别器(​discriminator​)元素就是被设计来应对这种情况的,另外也能处理其它情况,例如类的继承层次结构。 鉴别器的概念很好理解——它很像 Java 语言中的 switch 语句。

一个鉴别器的定义需要指定 ​column ​和 ​javaType ​属性。​column ​指定了 MyBatis 查询被比较值的地方。 而 ​javaType ​用来确保使用正确的相等测试(虽然很多情况下字符串的相等测试都可以工作)。例如:

<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>

在这个示例中,MyBatis 会从结果集中得到每条记录,然后比较它的 ​vehicle type​ 值。 如果它匹配任意一个鉴别器的 case,就会使用这个 case 指定的结果映射。 这个过程是互斥的,也就是说,剩余的结果映射将被忽略(除非它是扩展的,我们将在稍后讨论它)。 如果不能匹配任何一个 case,MyBatis 就只会使用鉴别器块外定义的结果映射。 所以,如果 ​carResult ​的声明如下:

<resultMap id="carResult" type="Car">
<result property="doorCount" column="door_count" />
</resultMap>

那么只有 ​doorCount ​属性会被加载。这是为了即使鉴别器的 case 之间都能分为完全独立的一组,尽管和父结果映射可能没有什么关系。在上面的例子中,我们当然知道 cars 和 ​vehicles ​之间有关系,也就是 Car 是一个 ​Vehicle​。因此,我们希望剩余的属性也能被加载。而这只需要一个小修改。

<resultMap id="carResult" type="Car" extends="vehicleResult">
<result property="doorCount" column="door_count" />
</resultMap>

现在 ​vehicleResult ​和 ​carResult ​的属性都会被加载了。

可能有人又会觉得映射的外部定义有点太冗长了。 因此,对于那些更喜欢简洁的映射风格的人来说,还有另一种语法可以选择。例如:

<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultType="carResult">
<result property="doorCount" column="door_count" />
</case>
<case value="2" resultType="truckResult">
<result property="boxSize" column="box_size" />
<result property="extendedCab" column="extended_cab" />
</case>
<case value="3" resultType="vanResult">
<result property="powerSlidingDoor" column="power_sliding_door" />
</case>
<case value="4" resultType="suvResult">
<result property="allWheelDrive" column="all_wheel_drive" />
</case>
</discriminator>
</resultMap>

请注意,这些都是结果映射,如果你完全不设置任何的 result 元素,MyBatis 将为你自动匹配列和属性。所以上面的例子大多都要比实际的更复杂。 这也表明,大多数数据库的复杂度都比较高,我们不太可能一直依赖于这种机制。