mybatis升级后导致alias表名设置设备诊断
mybatis从1.3.2 升级 2.0.7到后部分系统解析 alias出错了,具体错误如下:
问题触发位置:
- TypeAliasRegistry.registerAlias
- SqlSessionFactoryBean.buildSqlSessionFactory
下面从TypeAliasRegistry.registerAlias 开始逐步分析两个版本差异和抛出问题原因。
跟踪表名设置底层原理
两个版本的 TypeAliasRegistry.registerAlias 逻辑一致。具体代码如下。
# TypeAliasRegistry.java
public void registerAlias(Class<?> type) {
String alias = type.getSimpleName();
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
registerAlias(alias, type);
}
从代码中可以看出,mybatis别名使用 class 的 simpleName。如果多个包中出现实体名称,那么就会发送如上错误。
但是开发反馈mybatis升级前不存在该问题,需要继续向上追踪代码。下面是根据升级前后两个版本别名设置分析。
分析 SqlSessionFactoryBean.buildSqlSessionFactory 实现机制差异
-
mybatis-spring 1.3.2 typeAliasesPackage 解析逻辑如下
# SqlSessionFactoryBean protected SqlSessionFactory buildSqlSessionFactory() throws IOException { ... if (hasLength(this.typeAliasesPackage)) { String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packageToScan : typeAliasPackageArray) { configuration.getTypeAliasRegistry().registerAliases(packageToScan, typeAliasesSuperType == null ? Object.class : typeAliasesSuperType); if (LOGGER.isDebugEnabled()) { LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases"); } } } ... } # TypeAliasRegistry public void registerAliases(String packageName, Class<?> superType){ ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>(); resolverUtil.find(new ResolverUtil.IsA(superType), packageName); Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses(); for(Class<?> type : typeSet){ // Ignore inner classes and interfaces (including package-info.java) // Skip also inner classes. See issue #6 if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) { registerAlias(type); } } }
跟踪代码发现 typeAliasesPackage 不支持路径正则表达式;*实际配置 type-aliases-package: cn.pinming.suppervision..entity 无效。***
-
mybatis-spring 2.0.7 typeAliasesPackage 源码分析
#SqlSessionFactoryBean protected SqlSessionFactory buildSqlSessionFactory() throws Exception { if (hasLength(this.typeAliasesPackage)) { scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream() .filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface()) .filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias); } } private Set<Class<?>> scanClasses(String packagePatterns, Class<?> assignableType) throws IOException { Set<Class<?>> classes = new HashSet<>(); String[] packagePatternArray = tokenizeToStringArray(packagePatterns, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); for (String packagePattern : packagePatternArray) { Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(packagePattern) + "/**/*.class"); for (Resource resource : resources) { try { ClassMetadata classMetadata = METADATA_READER_FACTORY.getMetadataReader(resource).getClassMetadata(); Class<?> clazz = Resources.classForName(classMetadata.getClassName()); if (assignableType == null || assignableType.isAssignableFrom(clazz)) { classes.add(clazz); } } catch (Throwable e) { LOGGER.warn(() -> "Cannot load the '" + resource + "'. Cause by " + e.toString()); } } } return classes; }
该版本 typeAliasesPackage 已经支撑路径正则表达式。如 /a/b//c。原来解析不了的配置现在能解析了。**
问题解决方案
由于旧版本 mybatis 的 typeAliasesPackage配置不支撑正则表达式,原来的配置是无效的,所以没有报错。而新版本支撑正则表达式,能将以前无效的配置解析出来,但存在类名简称存在重复。所以导致出现了上面描述的问题。
方案一、项目中如果存在同名实体,修正同名实体。
方案二、移除typeAliasesPackage。不在mybatis中使用别名。比如输入不存在的报名:cn.pinming.suppervision.aaaaa
mybatis:
base-packages: cn.pinming.suppervision.**.dao,cn.pinming.suppervision.push.mapping,cn.pinming.suppervision.web.test.sys
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: cn.pinming.suppervision.aaaaa
mybatis 升级后 Specified class is an interface 错误
问题原因:新版本 mapper-spring-boot-starter 提供了 mapper-spring-boot-autoconfigure 实现,和自己定义的 有冲突。排除依赖即可。
解决方案
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!