constructor
<resultMap id="UserBasic" type="com.alibaba.force.dal.model.capsulation.UserBasic">
<constructor>
<arg column="u_name" jdbcType="VARCHAR" javaType="java.lang.String"/>
<arg column="u_username" jdbcType="VARCHAR" javaType="java.lang.String"/>
<arg column="u_id" jdbcType="BIGINT" javaType="java.lang.Long"/>
<arg column="u_state" jdbcType="VARCHAR" javaType="java.lang.String"/>
<arg column="u_avatar" jdbcType="VARCHAR" javaType="java.lang.String"/>
<arg column="u_extern_uid" jdbcType="VARCHAR" javaType="java.lang.String"/>
</constructor>
</resultMap>
@ToString
@Getter
@Setter
public class UserBasic extends UserSafe {
private Long id;
private String state;
@JSONField(name = "avatar_url")
private String avatarUrl;
@JSONField(name = "extern_uid")
private String externUid;
/**
* @param name
* @param username
* @param id
* @param state
* @param avatar 注意,这里需要做一些额外操作
* @param externUid
*/
public UserBasic(String name, String username, Long id, String state, String avatar, String externUid) {
super(name, username);
this.id = id;
this.state = state;
this.externUid = externUid;
this.setAvatarUrl(UsersUtil.getAvatarUrl(UsersBuilder.newBuilder().setId(id).setAvatar(avatar)
.setExternUid(externUid).build()));
}
public UserBasic() {
}
@Override
public UserBasic merge(@NonNull Users users) {
super.merge(users);
this.setId(users.getId());
this.setState(users.getState());
this.setAvatarUrl(UsersUtil.getAvatarUrl(users));
this.setExternUid(users.getExternUid());
return this;
}
}
注意入参的顺序保持一致
association
association
字段可以直接增加ResultMap
的子属性。
<resultMap id="MigrateTaskRecordDO" type="com.alibaba.force.dal.model.capsulation.MigrateTaskRecordDO">
<id column="id" jdbcType="BIGINT" property="id" />
<id column="u_id"/>
<result column="gmt_create" jdbcType="TIMESTAMP" property="gmtCreate" />
<result column="gmt_modified" jdbcType="TIMESTAMP" property="gmtModified" />
<association property="creator" javaType**="com.alibaba.force.dal.model.capsulation.UserBasic" resultMap="UserBasic"/>
</resultMap>
association
中的resultMap
所指向的字段也必须是申明过的ResultMap
对象。
result
需要放置在association
之前。
N+1问题
注意上面例子中的多个
有这么一个场景,会产生坑:
当查询1对多的关系时,如果采用了嵌套的方式(association、collection),则MyBatis会在DefaultResultSetHandler
中调用handleRowValuesForNestedResultMap
方法。
该方法采用了计算key(createRowKey
)的方式来记录已经遍历过的对象,并且下次从缓存中拿(减少内存的消耗,共享嵌套的重复对象)。
而由于N+1的select一定是根据这个“1”去查询其他的“N”的,如果此时<id>
不变,为主键,那么就会被丢弃很多结果(理论上不重复,但是由于上述的计算规则,被MyBatis认为是重复)。因此,使用多个联合字段作为id是最棒的解。这些联合ID需要是最终确定一个不重复对象的唯一值。
MyBatis版本:3.4.4