Mybatis(plus)映射为javaBean之List<String>属性set方法不生效

使用mybatis查询,并映射为javaBean时。数据库直接查询,该属性字段有值,但每次属性的set方法被调用时入参都是空,然而在mybatis最终的返回中,javaBean的属性又全都出现了值。这等诡异事件是如何发生的呢?

场景需求:将sql查询结果映射到javaBean中的一个List属性,同时通过该属性set方法,在里面做一些操作。
在这里插入图片描述
现象:mybatis查询后,调用了List roles属性的set方法,但是入参是空数组,但在对象构建完成后,roles却又出现了2个值。

set方法调用情况:
在这里插入图片描述

mybatis返回的对象结果:
在这里插入图片描述

依赖如下:

 <dependency>
        <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

猜想:
1.mybatis调用set方法注入的是一个空数组,然后将地址给实体属性,再往注入的数组中加入值,从而达到目的。
2.mybatis查询结果返回的对象在创建后,返回前被修改过,比如反射。

验证
方案一:
将属性set方法重写为:
图片
重新请求,现象完全一致,因此应该不是方案1导致。

方案二验证
查询处打一个断点,跟着代码走,
在这里插入图片描述

发现Sql执行完成后会走到一个BeanWrapper --> setBeanProperty方法
图片
解释说明:object就是创建的bean,value是值,prop是属性相关的东西,大约长下图这样。
此时可用看到value确实也是一个空数组,根据之前的信息,其有值的情况是发生在这之后的,所以继续往后走。
图片

到达 DefaultResultSetHandler -->applyNestedResultMappings方法时,发现此时roles属性仍旧是一个空数组
图片但是此时也发现了我们所需要的数据
在这里插入图片描述
因为知道数组大小是2,因此放过一次,验证是否是这里将值放进去了。
图片

果然,此时roles数组中已经放入了一个值,所以便继续进入DefaultResultSetHandler -->linkObjects查看是如何放入数据的。此时关闭其他地方所有断点,仅留下此一处。
图片
instantiateCollectionPropertyIfAppropriate目的是初始化参数, 并未改变值。roles这个属性值发生改变(数组中增加数据)的时候是targetMetaObject.add(rowValue);这个方法调用后。
图片
查资料发现,MetaObject是一个强大的反射工具类,支持查找属性(忽略大小写、支持驼峰、支持子属性)、查找子属性(“user.name”、"users[0].id"获取集合中子属性的值、"user[name]"获取map)、支持设置子属性。
也就说猜想2也不全对,初始化前后调用的是同一个类,只是加入值时是调用的list的add方法。那我们就进一步验证.

// 1.重写List的Add方法
public class MyList<E> extends ArrayList {    
		@Override    
		public boolean add(Object o) {        
			System.out.println("add方法被调用了:" +  JSONObject.toJSONString(o));        
			return super.add(o);    
		}
}

//2.属性类型重写		
private MyList<String> roles;

// 3.set方法重写为    
public void setRoles(MyList<String> roles) {
		System.out.println("入参:" + JSONObject.toJSONString(roles));        
		this.roles = roles;   
}

重新启动服务验证,日志打印结果:
图片

总结:mybatis在映射查询结果为一个javaBean时,对于List类型,是先为其进行赋值(空数组,查询无结果的情况此文不论),然后通过MetaObject为其子类设置值,设置值时调用的是其子类方法(此处是List的add方法)。因此在javaBean中,对于List类型的数据,其set方法获得的是一个空数组,而值是在后续通过add方法的调用获得的。
因此,通过mybatis查询映射的List属性,并不能在该属性set方法中对其值做出处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值