MyBatis映射含两个相同Card内部类的Hand实例时card2为null的问题排查
问题原因
执行SELECT *时,两张Card表的id、number、color列名完全重复,MyBatis映射结果时无法区分哪些列属于card1、哪些属于card2。它只会把第一组匹配的列值映射到card1,card2对应的字段因找不到唯一匹配的列名,最终被设为null。
修复方案
需要给SQL查询中的重复列添加别名,再调整ResultMap的映射规则,让MyBatis能正确识别字段对应关系。
步骤1:修改SQL语句,为重复列添加别名
把SELECT *替换为明确列名,并给Card表的字段加上区分别名:
SELECT H.id AS hand_id, c1.id AS card1_id, c1.number AS card1_number, c1.color AS card1_color, c2.id AS card2_id, c2.number AS card2_number, c2.color AS card2_color FROM Hand H LEFT JOIN Card c1 ON H.card1_id = c1.id LEFT JOIN Card c2 ON H.card2_id = c2.id
步骤2:调整ResultMap映射
有两种实现方式:
方式一:用columnPrefix简化映射
利用MyBatis的columnPrefix属性,给每个association指定列前缀,自动匹配对应字段:
<resultMap id="handMap" type="com.company.handsmap.Hand"> <id column="hand_id" property="id"/> <association property="card1" resultMap="cardMap" columnPrefix="card1_"/> <association property="card2" resultMap="cardMap" columnPrefix="card2_"/> </resultMap> <resultMap id="cardMap" type="com.company.handsmap.Card"> <id column="id" property="id"/> <result column="number" property="number"/> <result column="color" property="color"/> </resultMap>
columnPrefix会自动将前缀与resultMap中的列名拼接,比如card1_+id对应SQL中的card1_id,以此完成映射。
方式二:在association中单独指定列映射
如果不想用前缀,也可以在每个association里单独配置列与属性的对应关系:
<resultMap id="handMap" type="com.company.handsmap.Hand"> <id column="hand_id" property="id"/> <association property="card1" type="com.company.handsmap.Card"> <id column="card1_id" property="id"/> <result column="card1_number" property="number"/> <result column="card1_color" property="color"/> </association> <association property="card2" type="com.company.handsmap.Card"> <id column="card2_id" property="id"/> <result column="card2_number" property="number"/> <result column="card2_color" property="color"/> </association> </resultMap>
修改完成后,MyBatis就能正确区分两张Card的字段,card2可正常获取数据。
内容的提问来源于stack exchange,提问作者Titus Li
相关产品推荐
相关产品推荐

