【mybatis多对一嵌套查询映射】用于嵌套查询association的collumn的字段本来有值但用于嵌套查询后值变为null的问题

本文探讨了MyBatis嵌套查询中遇到的deptno字段丢失问题,并通过实验找到解决方案。文中详细分析了resultMap的工作原理,揭示了列名映射顺序的重要性,最后建议在实际应用中优选嵌套结果而非嵌套查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景:原emp pojo没有dept field,为实验mybatis嵌套查询,新增这个field。emp pojo本来是有deptno这个field的,但是由于deptno这个值要用于嵌套查询(在resultMap的association的collumn设置),发现返回的emp结果中deptno值为null,emp结果中dept的deptno却有值,实际数据库表中也是有值的。

mapper语句如下:

单元测试结果如下:

原因:未知

解决办法:在association标签上面再加一行<result property="deptno" column="deptno"/>,似乎得先标记一下,否则这个字段在用于association后就会变为null。

单元测试结果如下:

事后回顾:原因应该是resultMap会将用过的列名进行排除,并且显式映射的顺序优先,但是嵌套查询的column条件可以从被使用过的列名中取。估计如果将<result property="deptno" column="deptno"/>加在association标签下面,deptno也可能是null(如果嵌套标签的优先级与result标签的优先级相同的话,则先来先得,如果低于result优先级则不为null,要看mybatis内部实现)。启发来自参考文章,该文章有详细的mybatis配置步骤,从该文章的“嵌套结果部分”学生有id,年级也有id,引起我的好奇,mybatis是怎样“智能的”把学生的id给学生而不是把年级的id给学生,猜测在join的两个表里如果有两个同名列,则resultMap里相同列名映射结果的顺序与表名在sql语句里的顺序一样,例如<result property="id" column="id">和<association javaType="grade"><result property="id" column="id"></association>则第一个id对应第一个join表,第二个id对应第二个join表。该文章在“嵌套查询部分”提出的问题很有意思,估计column这个字段作为主查询中用于嵌套查询的参数,其名称不一定与select中的#{xxx}相同,因此嵌套查询中如果有动态sql会报xxx查不到。作者将动态sql去掉并且#{xxx}占位符取啥名都不影响,也不报错了,这种情况下的查询参数可能是直接按顺序赋值的,如column={"a","b"}对应#{第一个}、#{第二个}。这些顺序上的有趣之处可能跟resultSet.getString/getIndex有关。

总结:嵌套查询可能出现N+1的问题,还是用嵌套结果比较好。

待做:参考文章中作者说student和grade有同名的id和name字段会导致grade的id和name都变成了student的,这个需要试验一下。按我的理解,resultSet的值取过就没有了。实验了下,确实如此,最好将两个表的同名字段改成不一样,另外发现改成不一样后,所有的值都得显式映射,不映射的就会为null或0。在嵌套结果时,自动映射似乎只针对非嵌套的情况,把association或collection块注释掉。

PS:最近做了实验,<result property="deptno" column="deptno"/>加在association标签下面会报错,Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 12; columnNumber: 17; 元素类型为 "resultMap" 的内容必须匹配 "(constructor?,id*,result*,association*,collection*,discriminator?)"。看来解析的文件格式是有顺序要求的。

参考链接:

https://www.cnblogs.com/chiangchou/p/mybatis-association.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值