Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when use @RefreshScope on @Mapper #476

Closed
polarloves opened this issue Jun 1, 2020 · 14 comments · Fixed by #484
Closed

when use @RefreshScope on @Mapper #476

polarloves opened this issue Jun 1, 2020 · 14 comments · Fixed by #484
Assignees
Labels
enhancement Improve a feature or add a new feature

Comments

@polarloves
Copy link

polarloves commented Jun 1, 2020

I'm trying to get a dynamic datasource on mybatis.
while i use @RefreshScope on dao interface,an exception will occur.
the code is :
ClassPathMapperScanner ,line:196
beacuse it war RootBeanDefinition,not GenericBeanDefinition .
i can only fix it by change the source code on MapperScannerConfigurer :

  ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry) {
            @Override
            public Set<BeanDefinitionHolder> doScan(String... basePackages) {
                Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
                if (!beanDefinitions.isEmpty()) {
                    for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitions) {
                        // set scope
                        beanDefinitionHolder.getBeanDefinition().setScope("refresh");
                    }
                }
                return beanDefinitions;
            }
        };
@kazuki43zoo
Copy link
Member

Could you provide a small reproduce project?

@polarloves
Copy link
Author

Could you provide a small reproduce project?

https://github.com/polarloves/mybatis-test

@kazuki43zoo
Copy link
Member

@polarloves

Thanks you for providing a reproduce project!
In current implementation, mybatis-spring does not support for scanning a scoped proxy bean.
In this case, TestDao has bean scaned as "refresh" scoped proxy bean by bean definition scanner provided by Spring Framework because @RefreshScope adding.

I will consider to support scoped proxy bean at next version.

I have a one question.
Does Mapper need to be in refresh scope? If so, can you explain why?

@kazuki43zoo kazuki43zoo self-assigned this Jun 17, 2020
@kazuki43zoo kazuki43zoo added enhancement Improve a feature or add a new feature and removed enhancement Improve a feature or add a new feature labels Jun 17, 2020
@kazuki43zoo
Copy link
Member

FYI:
You can prevent this error by changed to @RefreshScope(proxyMode = ScopedProxyMode.NO), but you need an attention to the scope of the component that injects the mapper.

@Mapper
@RefreshScope(proxyMode = ScopedProxyMode.NO)
public interface TestDao {
  // ...
}

@polarloves
Copy link
Author

@polarloves
Thanks you for providing a reproduce project!
In current implementation, mybatis-spring does not support for scanning a scoped proxy bean.
In this case, TestDao has bean scaned as "refresh" scoped proxy bean by bean definition scanner provided by Spring Framework because @RefreshScope adding.
I will consider to support scoped proxy bean at next version.
I have a one question.
Does Mapper need to be in refresh scope? If so, can you explain why?

I am trying to provider two functiones on my project : "dynamic database" and "config mybatis on config center ".
for dynamic database, the database may change to another machine,I donot want to restart my project (i am lazy enough),I want change the config property on config center such as nacos, so I make the datasource dynamic ,but i found the Mapper use the old datasource,so i have to change its scope to "refresh".besides, I donnot want to use @RefreshScope annotation ,I want to change its scope by my code so that I can switch between "dynamic database" and "static database",i am tried to write a class extends MapperScannerConfigurer, but the MapperScannerConfigurer donot support a public function to change Mapper's scope.I know spring does not suggest dynamic database ,but I want to try~

for "config mybatis on config center ",i want move Mybatis-config.xml to config center,but mybatis does not support yml parser,so i write one.I think is ok.

这个老外看得懂中文吗?

@kazuki43zoo
Copy link
Member

so I make the datasource dynamic ,but i found the Mapper use the old datasource,

Could you provide a reproduce project? I'm not familiar to Spring Cloud, can't it be resolved by making the DataSource a refresh scoped bean?

config mybatis on config center

Have you tried MyBatis Spring Boot?
It can be configure the SqlSessionFactory using spring boot configuration properties feature.

@polarloves
Copy link
Author

so I make the datasource dynamic ,but i found the Mapper use the old datasource,

Could you provide a reproduce project? I'm not familiar to Spring Cloud, can't it be resolved by making the DataSource a refresh scoped bean?

config mybatis on config center

Have you tried MyBatis Spring Boot?
It can be configure the SqlSessionFactory using spring boot configuration properties feature.

https://github.com/mybatis/spring-boot-starter

when use @RefrshScope on Datasource ,the bean who use Datasource must use @RefreshScope too。so mybatis should use @RefreshScope

@polarloves
Copy link
Author

so I make the datasource dynamic ,but i found the Mapper use the old datasource,
Could you provide a reproduce project? I'm not familiar to Spring Cloud, can't it be resolved by making the DataSource a refresh scoped bean?
config mybatis on config center
Have you tried MyBatis Spring Boot?
It can be configure the SqlSessionFactory using spring boot configuration properties feature.
https://github.com/mybatis/spring-boot-starter

when use @RefrshScope on Datasource ,the bean who use Datasource must use @RefreshScope too。so mybatis should use @RefreshScope

when the envirment changed spring will create a new context,and product some new beans,the beans in old context who was in refresh scope will be replace by new beans .if some bean not in refresh scope.it will not be replaced! if i only add RefreshScope on Datasource,the Dao will not be a new one and its datasource is also old one.

@kazuki43zoo
Copy link
Member

I think it can be resolved that creating a DataSource as scoped proxy.
If possible, please provide a small prototype project. There is possible that I can help you.

@kazuki43zoo
Copy link
Member

@polarloves

I've created a demo application(prototype application) for this issue.

Could you try it and please feedback if possible. Thanks!

@kazuki43zoo
Copy link
Member

@polarloves

You can change MyBatis's beans(SqlSessionFactory and mapper beans ) to refresh scope using 'spring.cloud.refresh.refreshable' property provided spring-cloud as follow:

spring.cloud.refresh.refreshable=org.apache.ibatis.session.SqlSessionFactory,org.mybatis.spring.mapper.MapperFactoryBean

For details and sample, please see a demo application(prototype application).

@kazuki43zoo
Copy link
Member

See spring-projects/spring-boot#22038 about auto-configure of mybatis-spring-boot-starter is disabled when DataSource is refresh scope.

@kazuki43zoo kazuki43zoo added the enhancement Improve a feature or add a new feature label Jun 20, 2020
@kazuki43zoo kazuki43zoo added this to the 2.0.6 milestone Jun 21, 2020
kazuki43zoo added a commit to kazuki43zoo/spring that referenced this issue Jun 21, 2020
kazuki43zoo added a commit to kazuki43zoo/spring that referenced this issue Jun 21, 2020
kazuki43zoo added a commit to kazuki43zoo/spring that referenced this issue Jun 21, 2020
@kazuki43zoo kazuki43zoo removed this from the 2.0.6 milestone Jun 21, 2020
kazuki43zoo added a commit that referenced this issue Jun 21, 2020
@kazuki43zoo
Copy link
Member

@polarloves

I support to specifies the default scope on mapper scanning features(@MapperScan, MapperScannerConfigurer, <mybatis:scan />) and define scope annotation(@Scope, @RefreshScope, etc ...) at mapper interface.

For details, please see the following PR/Issue.

@kazuki43zoo
Copy link
Member

See spring-projects/spring-boot#22038 about auto-configure of mybatis-spring-boot-starter is disabled when DataSource is refresh scope.

Already fixed on 2.2.9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improve a feature or add a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants