mybatisplus 如何动态创建 mapper 接口。

2022-01-23 22:54:46 +08:00
 lawler

在写一个涉及单表操作较多的系统。

框架组合,spring boot + mybatis plus 。 代码结构,entity -> mapper -> service -> controller

但是要创建非常多的空白 mapper/service/controller 的 java 文件。

mapper 是个纯接口的空文件,不想写这么多空文件在代码里,如何做到动态注入“接口”文件?

@Mapper public interface EntityMapper extends BaseMapper {

}

甚至,service ,和 Iservice ,也希望通过实体动态生成,直接映射出来接口。

或者有其他方案?可以尽可能的专注业务功能。

4192 次点击
所在节点    Java
32 条回复
monkeyWie
2022-01-24 12:02:38 +08:00
@lawler #18 应该可以实现,但是不能按 type 注入,然后你得找到 mybatis-plus mapper 的实现,批量注册 bean 就行了
makinomura
2022-01-24 12:03:51 +08:00
@lawler BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 这个里面注册 beanDefinition 即可,注意要使用 MapperFactoryBean
aguesuka
2022-01-24 17:09:22 +08:00
你是不是想只要有实体类 Entity, 就可以 @Autowired 注入 BaseMapper<Entity> 然后统一使用 LambdaQueryWrapper?
这样的话有两个步骤, 根据 Entity.class 生成 EntityWapper implements BaseMapper<Entity>, 将 EntityWapper 注入到 Spring. 现在的进展如何了?
lawler
2022-01-24 21:48:28 +08:00
@makinomura #22 尝试很久,搞不会了,XY 问题太多。麻烦大佬再指点一下。

1 ,BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
- 注册过程中,我需要写大量逻辑判断,来确认哪些是数据库实体。
- 或者,我需要一个自定义注解来过滤上个问题?

2 ,MapperFactoryBean 该如何使用?
- new 一个不可能,因为有上下文环境。
- 不 new 的时候,他还在第 1 步中,需要我写逻辑判断处理摘出来。再使用他?
- 鉴于以上两个问题,我不知道怎么使用他。
wolfie
2022-01-25 14:34:18 +08:00
https://github.com/wolfiesonfire/dynamic-mapper

使用 byte buddy 运行时创建 mapper + service 。
但是 ServiceImpl 的 baseMapper, Autowired 有点问题。
lawler
2022-01-25 15:25:43 +08:00
@wolfie #25 十分感谢,service 的 mapper 注入我倒是有办法,我今天有点忙,明天我验证一下,没有问题的话把后续完善一下提 pr 给你看看。

另,小年快乐。
keshawnvan
2022-01-25 16:49:01 +08:00
看下 tkMybatis 提供的 ActiveRecord 模式
makinomura
2022-01-26 10:37:31 +08:00
@lawler #24 我简单写了个 demo
makinomura
2022-01-26 10:38:16 +08:00
public class DomainScanner extends ClassPathBeanDefinitionScanner {
public DomainScanner(BeanDefinitionRegistry registry) {
super(registry, false);
}

@Override
protected boolean isCandidateComponent(MetadataReader metadataReader) {
return true;
}

@Override
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(
basePackages);
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
ScannedGenericBeanDefinition beanDefinition = (ScannedGenericBeanDefinition) beanDefinitionHolder
.getBeanDefinition();
String beanClassName = beanDefinition.getBeanClassName();
Class<?> entityClazz = null;
try {
entityClazz = Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(beanClassName);
}
DynamicMapperCreator dynamicMapperCreator = new DynamicMapperCreator();
Class<?> mapperClazz = dynamicMapperCreator
.getOrCreateMapperClazz(entityClazz);
beanDefinition.setBeanClass(MapperFactoryBean.class);
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0, mapperClazz);
beanDefinition
.setConstructorArgumentValues(constructorArgumentValues);
beanDefinition.getPropertyValues().add("sqlSessionFactory",
new RuntimeBeanReference("sqlSessionFactory"));
}

return beanDefinitionHolders;
}
}

public class MapperRegister implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
new DomainScanner(registry).scan("umoo.wang.domain");
}

@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
Chinsung
2022-01-26 11:28:02 +08:00
可以用 java agent 的方式,去扫描你自定义某个包下的所有 do 类,然后通过字节码框架,比如 bytebuddy 这种,生成所有的 mapper 类
Chinsung
2022-01-26 11:30:10 +08:00
@Chinsung #30 不过这样会在编译期有问题
lawler
2022-01-28 13:57:47 +08:00
回复一下说下现状。
#25 #29 方案都试过,可以是可以。但还是存在我强调的加载时机问题。

主要问题是,当代码中存在,@PostConstruct 时,因未被编译并注册,所以找不到依赖。

目前已经放弃了这个想法。但计划空闲的时候,参考 lombok 的方式,注解生成。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/830149

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX