MyBatis Plus有一个很大的缺陷,就是insert和select的时候使用的ResultMap是不同的,修复的办法就是在实体类上增加注解
@TableName(autoResultMap = true)
。但是这个autoResultMap并不能使用在自定义的方法上,只在MyBatis Plus内置方法上生效。
展示autoResultMap存在的问题
- 实体类Person
该实体类中有自定义的typehandler: IntegerListTypeHandler, StringListTypeHandler
@TableName(autoResultMap = true)
public class Person {
private Integer id;
private String name;
private Integer age;
@TableField(typeHandler = IntegerListTypeHandler.class)
private List<Integer> orgIds;
@TableField(typeHandler = StringListTypeHandler.class)
private List<String> hobbies;
}
@Mapper
public interface PersonMapper extends BaseMapper<Person> {
/**
* 自定义的根据Id获取Person的方法,与MyBatis-Plus中的selectById相同的功能(但是不能使用autoResultMap生成的ResultMap).
*/
@Select("SELECT * FROM person WHERE id=#{id}")
Person selectOneById(int id);
}
- 自定义方法拿不到一些字段
因为Person中的orgIds和hobbies需要自定义的typeHandler,自定义的方法使用的是resultType=Person,而不是生成的ResultMap,所以都是null
Person person = new Person();
person.setAge(1);
person.setName("tim");
person.setOrgIds(Lists.newArrayList(1,2,3));
person.setHobbies(Lists.newArrayList("basketball", "pingpong"));
personMapper.insert(person);
# 可以得到正确的字段值
Person personInDb = personMapper.selectById(person.getId());
# orgIds和hobbies都为null
personInDb = personMapper.selectOneById(person.getId());
Preconditions.checkArgument(personInDb.getHobbies().equals(person.getHobbies()));
Preconditions.checkArgument(personInDb.getName().equals(person.getName()));
Preconditions.checkArgument(personInDb.getAge().equals(person.getAge()));
Preconditions.checkArgument(personInDb.getOrgIds().equals(person.getOrgIds()));
改进
- 设置
@ResultMap("mybatis-plus_Person")
/**
* 设置了ResultMap为`mybatis-plus_Person`后就可以拿到正确的值.
*/
@ResultMap("mybatis-plus_Person")
@Select("SELECT * FROM person WHERE id=#{id}")
Person selectOneById(int id);
命名规则就是:mybatis-plus_{实体类名}
个人理解
MyBatis Plus本身并不是一个动态的ORM,而只是在mybatis初始化的时候,为mybatis提供常用的SQL语句,resultMap设置,并不会改变MyBatis本身的行为
常见问题
-
@TableField(typeHandler = IntegerListTypeHandler.class)
没有生效:自定义的方法上没有配置resultType
网友评论