问题

公司有一个集成开发平台,导入数据库表会自动生成实体类、mapper和xml等文件,这是一件很方便的事,可以省去很多没有技术性的重复工作。

但是最近我在使用这个平台的时候遇到了一个问题,那就是mapper冲突问题。当老表进行导入的时候,会生成与之前项目中已有mapper一样的名字,比如原项目中有个PersonMapper.java的文件,导入后就会有两个PersonMapper.java,这样就会冲突报错,导致项目无法启动。

怎么解决呢?将原先的mapper命名进行修改?显然是不现实的,也违背了开放封闭原则。

原因

首先需要明确,为什么两个一样命名的mapper文件会冲突,因为在在进行对象注入的时候,@Mapper在生成beanName的时候默认把首字母小写之后返回类名,如果存在两个命名完全一样的文件返回的beanName也是一样的,因此@Resource会不知道注入哪一个从而冲突。

清楚原因后,要做的就是当注入的时候怎么区分这两个mapper文件,进行不同的注入。

解决

在思考一番后,决定使用@MapperScan去解决这个问题,核心在于使用其中的nameGenerator字段。

@MapperScan中的nameGenerator继承于BeanNameGenerator



而在Spring的容器中,是使用BeanNameGenerator去命名检测到的组件,可以通过重写nameGenerator方法去重命名检测到的组件,具体解决代码如下所示:

@Configuration
@MapperScan(
value = {"xxx", "xxx"},
sqlSessionFactoryRef = "sqlSessionFactory",
nameGenerator = ComposerNameGenerator.class
) public class ComposerNameGenerator implements BeanNameGenerator {
public ComposerNameGenerator() {
} // definition 是被生成名字的BeanDefinition实例;
// registry是生成名字后注册进的BeanDefinitionRegistry。
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
// 拿到Bean定义信息里面的BeanClassName全类名
// 注意这个不是必须的,因为如果是继承关系,配上父类的依旧行了
String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
// 若没有配置本类全类名,去拿到父类的全类名+$child"俩表示自己
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
}
// 工厂Bean的 就用方法的名字+"$created"
else if (definition.getFactoryBeanName() != null) {
generatedBeanName = definition.getFactoryBeanName() + "$created";
}
}
// 若一个都没找到,抛错
if (!StringUtils.hasText(generatedBeanName)) {
throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither 'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
} else {
return generatedBeanName;
}
}
}

这样配置后,即使是一样命名的mapper文件,只要不在同一个包中依旧可以正常注入。

解决mapper重名问题的更多相关文章

  1. C#显示声名接口就是为了解决方法重名的问题

    class class1 { public static void Main(string[] args) { Person ps = new Person(); ps.KouLan(); IFlya ...

  2. JS重名解决方案

    一个页面如果引用多个JS,或者像ASP.NET MVC,一个视图包含多个子视图,每个子视图有自己的JS,那么变量.函数的重名冲突机会将会大增. 如何解决? 这里有一个方案: 1.用类来封装子页的JS代 ...

  3. 4.4 ROS节点名称重名

    4.4 ROS节点名称重名 场景:ROS 中创建的节点是有名称的,C++初始化节点时通过API:ros::init(argc,argv,"xxxx");来定义节点名称,在Pytho ...

  4. android - 解决“应用自定义权限重名”

    背景 现场的开发今天跟我说,测试包装不上!报错"应用自定义权限重名"!!! 网上百度下关键字,发现魅族手机有这个毛病,顺藤摸瓜:"http://bbs.flyme.cn/ ...

  5. com.google.gson的SerializedName解决实体类与关键字的重名

    使用google的gson包,解决实体类中字段与java关键字的重名: // 比如 当实体类中有switch关键字时,解决冲突如下 @SerializedName("switch" ...

  6. java 实现多个接口 方法重名的解决办法——内部类

    package com.kk.innerClass; /** * 通过内部类实现接口 * 解决多个接口中方法重名问题 * */interface Machine { void run();} clas ...

  7. Mybatis中多表联查,查询出来的字段出现重名,造成数据异常的解决方法!

    在做一对多出现的问题,引发的思考:当数据库表中,主表的主键id和明细表的中的字段名相同时怎么办?Mybatis进行自动映射赋值的时候会不会出现异常?                      注意:M ...

  8. db2 v9.5迁移至v10.5,及遇重名节点数据库无法创建db的解决办法

    同系统同版本可以使用备份恢复,本文前提是不同系统不同版本,使用db2move命令. 1.db2move db db_name export 此处注意,先建个目录放文件,因为文件比较多,如果上来直接ex ...

  9. MySql 外键重名问题

    在使用mysql workbench 来设计数据库模型时可能一不注意就会出现外键约束重名的情况,并在执行sql语句是会报这样的错误: Error 1022 - Can't write; duplica ...

  10. Django中上传图片---避免因图片重名导致被覆盖

    上一篇文章中(https://www.cnblogs.com/lutt/p/10640412.html),我们以图片文件夹+图片名字的方式来储存图片,这样的做法会导致有重名的图片会导致之前的图片被覆盖 ...

随机推荐

  1. NIO和传统IO

    传统 IO 基于字节流或字符流(如 FileInputStream.BufferedReader 等)进行文件读写,以及使用 Socket 和 ServerSocket 进行网络传输. NIO 使用通 ...

  2. 数据分析(matplotlib pyplot)

    文章目录 1.导入pyplot 库 2.绘出直线图 3.绘出实心点 4.绘出折线图 5.绘制正余弦函数 Pyplot 是 Matplotlib 的子库,提供了和 MATLAB 类似的绘图 API. P ...

  3. OpenGL常用函数整理

    常用函数 颜色设置 glClear(GL_COLOR_BUFFER_BIT); //清空颜色,GL_COLOR_BUFFER_BIT是颜色缓冲区 glClearColor(R,G,B,A); //设置 ...

  4. 【笔记】 STL容器

    [笔记] STL容器 vector vector<int> v; v.push_back(x); v.emplace(x); v.size(); v.erase(v.begin(),v.b ...

  5. .NET云原生应用实践(五):使用Blazor WebAssembly实现前端页面

    本章目标 使用Blazor WebAssembly实现管理"贴纸"页面 集成认证与授权机制 如果你对Blazor WebAssembly的使用不感兴趣,可以跳过本章的阅读.你也可以 ...

  6. 推荐一个Star超过2K的.Net轻量级的CMS开源项目

    推荐一个具有模块化和可扩展的架构的CMS开源项目. 01 项目简介 Piranha CMS是一个轻量级且跨平台的CMS库,专为.NET 8设计. 该项目提供多种模板,具备CMS基本功能,也有空模板方便 ...

  7. FFmpeg转码音视频时间戳设置分析

    音频时间戳设置 以下代码基于FFmpeg n5.1.2进行分析 以下文档中有关音频的具体时间戳数据来自以下转码命令: ./ffmpeg_g -rw_timeout 5000000 -i 'rtmp:/ ...

  8. Redis究竟为什么这么快?

    Redis为什么这么快? 完全基于内存,数据存在内存中,绝大部分请求是纯粹的内存操作,非常快速,跟传统的磁盘文件数据存储相比,避免了通过磁盘IO读取到内存这部分的开销. 数据结构简单,对数据操作也简单 ...

  9. apache tomcat 6集群负载和session复制

    无意间看到tomcat 6集群的内容,就尝试配置了一下,还是遇到很多问题,特此记录.apache服务器和tomcat的连接方法其实有三种:JK.http_proxy和ajp_proxy.本文主要介绍最 ...

  10. python语言实现_通过端口转发实现跨网络(多网络之间)通信_science_network

    本文使用python语言实现了一个端口转发的程序,该程序可以实现多网络之间的信息通信,当然这里有个前提,那就是多个网络都在一台主机上有可以连通的端口. 之所以有这个编写代码的需求,是因为最近使用的sc ...