如何让MyBatis支持Apache Commons Pair集合实现批量插入?
解决MyBatis识别Apache Commons Pair作为批量插入集合元素的问题
错误原因
从报错信息来看,MyBatis错误地将集合中的entry识别为User对象,而非你传入的Pair<AccountNumber, User>,所以才会去User类中寻找不存在的left属性。这通常是泛型擦除导致MyBatis无法正确推断集合元素的实际类型引发的。
可行解决方案
方案1:自定义DTO替代Pair(推荐)
自定义语义清晰的DTO类来封装AccountNumber和User的关联关系,避免第三方类带来的反射问题,同时代码可读性更强:
- 定义DTO类:
public class AccountUserPair { private AccountNumber accountNumber; private User user; public AccountUserPair(AccountNumber accountNumber, User user) { this.accountNumber = accountNumber; this.user = user; } // 仅需提供getter方法,MyBatis会自动映射 public AccountNumber getAccountNumber() { return accountNumber; } public User getUser() { return user; } }
- 修改Mapper接口:
void saveUsers(@Param("accountUsers") final List<AccountUserPair> accountUsers);
- 调整XML映射语句:
<insert id="saveUsers"> INSERT OR UPDATE INTO UserConfig(accountNumber, userId, role, ...) VALUES ( <foreach item="pair" index="index" collection="accountUsers" separator=","> (#{pair.accountNumber, javaType=com.my.company.dataid.account.AccountNumber}, #{pair.user.userId}, #{pair.user.role}, ... ) </foreach> ) </insert>
方案2:直接调用Pair的getter方法
绕过MyBatis的属性名映射,直接调用Apache Commons Pair的getLeft()和getRight()方法,避免泛型类型推断错误:
修改XML映射语句中的参数引用:
<insert id="saveUsers"> INSERT OR UPDATE INTO UserConfig(accountNumber, userId, role, ...) VALUES ( <foreach item="entry" index="index" collection="accountUsers" separator=","> (#{entry.getLeft(), javaType=com.my.company.dataid.account.AccountNumber}, #{entry.getRight().userId}, #{entry.getRight().role}, ... ) </foreach> ) </insert>
方案3:配置MyBatis反射规则(不推荐)
通过自定义Reflector或配置MyBatis的反射策略,让它能正确识别Pair的left/right属性,但这种方式配置复杂,且依赖MyBatis内部实现,后续版本升级可能出问题,因此不建议使用。
内容的提问来源于stack exchange,提问作者Patrick Proctor
相关产品推荐
相关产品推荐

