问题
Spring集成Mybatis的项目中,可以为指定包下的实体取别名,这样在Mapper xml文件中可以省略实体类的全路径名称,只写类名称即可;但是在多模块项目中,可能需要将实体放在不同的模块下,此时需要配置多路径扫描;
方式一:配置多个路径,逗号分隔符隔开
<!-- sqlSessionFactory spring 整合 mybatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- mybatis 核心配置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- mapper xml -->
<property name="mapperLocations">
<array>
<value>classpath*:mybatis/mapper/*.xml</value>
</array>
</property>
<!-- 实体类别名 多个路径扫描 -->
<property name="typeAliasesPackage" value="com.dongzz.cms.modules.a.entity,com.dongzz.cms.modules.b.entity" />
</bean>
方式二:采用通配符的方式配置,默认不支持此方式,需要对 SqlSessionFactoryBean
进行重写,使其支持通配符扫描
package com.dongzz.cms.common.plugin.mybatis;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义 SqlSessionFactoryBean
*/
public class SqlSessionFactoryBean extends org.mybatis.spring.SqlSessionFactoryBean {
public static final Logger logger = LoggerFactory.getLogger(SqlSessionFactoryBean.class);
public static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; // 别名通配符
/**
* 重写 实体别名扩展 支持通配符
*
* @param typeAliasesPackage 格式: com.dongzz.cms.modules.**.entity
*/
@Override
public void setTypeAliasesPackage(String typeAliasesPackage) {
// 资源路径解析器
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 元数据读取
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
// 解析路径
typeAliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/" + DEFAULT_RESOURCE_PATTERN;
logger.debug("别名包通配符:" + typeAliasesPackage);
try {
Set<String> result = new HashSet<>(); // 别名包路径集合
Resource[] resources = resolver.getResources(typeAliasesPackage); // 根据路径 读取所有的类资源
if (resources != null && resources.length > 0) {
MetadataReader metadataReader = null;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource); // 读取类的信息,每个 Resource 都是一个类资源
try {
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName()); // 存储类对应的包路径
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
if (result.size() > 0) {
logger.debug("别名包路径集合:" + StringUtils.join(result.toArray(), ","));
super.setTypeAliasesPackage(StringUtils.join(result.toArray(), ","));
} else {
logger.warn("Parameter typeAliasesPackage:" + typeAliasesPackage + ", not found any packages.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Xml配置:
<!-- sqlSessionFactory 采用自定义的 -->
<bean id="sqlSessionFactory" class="com.dongzz.cms.common.plugin.mybatis.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- mybatis 核心配置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- mapper xml -->
<property name="mapperLocations">
<array>
<value>classpath*:mybatis/mapper/*.xml</value>
</array>
</property>
<!-- 实体类别名 通配符扫描 -->
<property name="typeAliasesPackage" value="com.dongzz.cms.modules.**.entity" />
</bean>
通过自定义 SqlSessionFactoryBean
使得mybatis支持通配符别名扫描,这样在多模块项目中,扫描路径仅需要配置一次即可;