You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MyBatis抽象类结果映射失败:如何正确实例化对应子类?

问题描述

在使用MyBatis映射包含抽象密封类TariffDetails的UtilityDetails对象时,抛出java.lang.InstantiationException异常。原因是MyBatis尝试实例化抽象类TariffDetails,尽管已在Mapper XML中配置了discriminator,通过tariff_type字段区分TariffDetails的三个子类(TariffDualRateDetails、TariffSingleRateDetails、TariffSubscriptionDetails),但问题仍未解决。

问题原因分析

当前配置中,子类resultMap继承了抽象父类的tariffMap,MyBatis在处理时会优先尝试实例化父类(抽象类),再尝试转换为子类,这直接触发了实例化异常。此外,父类resultMap仅包含discriminator,未明确跳过父类实例化逻辑,导致MyBatis误执行抽象类的实例化流程。

解决方案

调整Mapper XML的resultMap配置,确保MyBatis直接根据discriminator的值实例化对应的子类,避免尝试实例化抽象父类。具体修改如下:

  1. 移除子类resultMap对父resultMap的继承
    子类resultMap无需继承抽象父类的resultMap,直接独立配置构造函数映射即可。

  2. 确保tariff_type字段返回有效值
    检查SQL中的case语句,确保每个查询结果都能返回匹配子类的tariff_type值(DUAL_RATE/SINGLE_RATE/SUBSCRIPTION),避免null值导致MyBatis找不到对应子类而尝试实例化父类。

修改后的Mapper XML核心配置:

<resultMap id="utilityDetails" type="org.upc.model.UtilityDetails">
    <constructor>
        <idArg name="id" column="u_id"/>
        <arg name="name" column="u_name"/>
        <arg name="createdAt" column="u_created_at"/>
        <arg name="archived" column="u_archived"/>
        <arg name="sortOrder" column="u_sort_order"/>
        <arg name="currentTariff" resultMap="tariffMap"/>
    </constructor>
</resultMap>

<resultMap id="tariffDualRate" type="org.upc.model.TariffDualRateDetails">
    <constructor>
        <idArg name="id" column="t_id"/>
        <arg name="utilityId" column="u_id"/>
        <arg name="createdAt" column="t_created_at"/>
        <arg name="threshold" column="tdr_threshold"/>
        <arg name="unitSize" column="tdr_unit_size"/>
        <arg name="thresholdComparison" column="tdr_threshold_comparison"/>
        <arg name="priceAboveThreshold" column="tdr_price_above_threshold"/>
        <arg name="priceBelowThreshold" column="tdr_price_below_threshold"/>
    </constructor>
</resultMap>

<resultMap id="tariffSingleRate" type="org.upc.model.TariffSingleRateDetails">
    <constructor>
        <idArg name="id" column="t_id"/>
        <arg name="utilityId" column="u_id"/>
        <arg name="createdAt" column="t_created_at"/>
        <arg name="price" column="tsr_price"/>
        <arg name="unitSize" column="tsr_unit_size"/>
    </constructor>
</resultMap>

<resultMap id="tariffSubscription" type="org.upc.model.TariffSubscriptionDetails">
    <constructor>
        <idArg name="id" column="t_id"/>
        <arg name="utilityId" column="u_id"/>
        <arg name="createdAt" column="t_created_at"/>
        <arg name="price" column="ts_price"/>
    </constructor>
</resultMap>

<resultMap id="tariffMap" type="org.upc.model.TariffDetails">
    <discriminator javaType="string" column="tariff_type">
        <case value="DUAL_RATE" resultMap="tariffDualRate"/>
        <case value="SINGLE_RATE" resultMap="tariffSingleRate"/>
        <case value="SUBSCRIPTION" resultMap="tariffSubscription"/>
    </discriminator>
</resultMap>
额外检查点
  • 确认SQL返回的tariff_type值与discriminator的case值大小写完全匹配
  • 验证子类构造函数的参数顺序、名称与resultMap中arg标签的name属性一一对应
  • 若使用低版本MyBatis,建议升级至3.5.0+版本,确保对抽象类判别器的支持

内容的提问来源于stack exchange,提问作者acanthite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:11:59