MyBatis Plus 启动扫描报错 The alias '' is already mapped to the value

问题

SpringBoot 项目启动时报错

1
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.apache.ibatis.type.TypeException: The alias '' is already mapped to the value 'com.java.balala.service$1'.

定位

查看 application.ymlmybatis-plus.typeAliasesPackage,发现扫描路径配置的地址为 com.java.balala.*,启动时会扫描整个项目找寻绑定的 entity
一般而言问题是扫描到的实体类名称相同,例如配置了扫描路径后,在路径下的不同的文件夹均有 userEntity 这个实体,默认会按照类名创建。
查找资料,MyBatis-Plus 会扫描配置路径下编译好的 class 文件全部加载为 class 对象进行处理,此时会把内部匿名类也算进去,而获取内部匿名类的别名为 ‘’。
排查源码源码定位到 registerAlias 方法,直接通过 type.getSimpleName() 获取了类的名称,如果是内部匿名类的别名会为 ‘’。

1
2
3
4
5
6
7
8
public void registerAlias(Class<?> type) {
String alias = type.getSimpleName();
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
registerAlias(alias, type);
}

排查代码发现报错处,只写了一个 switch,推测是 switch 创建了匿名类并冲突。

1
2
3
4
5
6
7
8
9
10
11
12
switch (type) {
case 1:
throw new RuntimeException("1");
case 2:
throw new RuntimeException("2");
case 3:
return dosomethings(3);
case 4:
return dosomethings(4);
default:
throw new RuntimeException("default");
}

解决

修改 application.ymlmybatis-plus.typeAliasesPackage,精确路径到实体类中,保证实体类名不冲突即可。
指定路径可以有多个,以逗号分隔即可。

1
2
3
4
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.java.balala.entity,com.java.lalala.entity