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

Change to support spring-native #618

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2021 the original author or authors.
* Copyright 2015-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@

import java.beans.PropertyDescriptor;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand All @@ -42,7 +43,9 @@
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
Expand All @@ -53,9 +56,11 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
Expand Down Expand Up @@ -208,9 +213,11 @@ public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory
* {@link org.mybatis.spring.annotation.MapperScan} but this will get typed mappers working correctly, out-of-the-box,
* similar to using Spring Data JPA repositories.
*/
public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar {
public static class AutoConfiguredMapperScannerRegistrar
implements BeanFactoryAware, EnvironmentAware, ImportBeanDefinitionRegistrar {

private BeanFactory beanFactory;
private Environment environment;

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Expand Down Expand Up @@ -242,6 +249,25 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
// Need to mybatis-spring 2.0.6+
builder.addPropertyValue("defaultScope", "${mybatis.mapper-default-scope:}");
}

// for spring-native
boolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class,
Boolean.TRUE);
if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory;
Optional<String> sqlSessionTemplateBeanName = Optional
.ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory));
Optional<String> sqlSessionFactoryBeanName = Optional
.ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory));
if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) {
builder.addPropertyValue("sqlSessionTemplateBeanName",
sqlSessionTemplateBeanName.orElse("sqlSessionTemplate"));
} else {
builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get());
}
}
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());
}

Expand All @@ -250,6 +276,16 @@ public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

private String getBeanNameForType(Class<?> type, ListableBeanFactory factory) {
String[] beanNames = factory.getBeanNamesForType(type);
return beanNames.length > 0 ? beanNames[0] : null;
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
"description": "A default scope for mapper bean that scanned by auto-configure.",
"type": "java.lang.String"
},
{
"defaultValue": true,
"name": "mybatis.inject-sql-session-on-mapper-scan",
"description": "Set whether inject a SqlSessionTemplate or SqlSessionFactory bean (If you want to back to the behavior of 2.2.1 or before, specify false). If you use together with spring-native, should be set true.",
"type": "java.lang.Boolean"
},
{
"name": "mybatis.scripting-language-driver.velocity.userdirective",
"deprecation": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Available properties are:
| `configuration-properties` | Externalized properties for MyBatis configuration. Specified properties can be used as placeholder on MyBatis config file and Mapper file. For detail see the [MyBatis reference page](http://www.mybatis.org/mybatis-3/configuration.html#properties). |
| `lazy-initialization` | Whether enable lazy initialization of mapper bean. Set `true` to enable lazy initialization. This feature requires to use together with mybatis-spring 2.0.2+. |
| `mapper-default-scope` | Default scope for mapper bean that scanned by auto-configure. This feature requires to use together with mybatis-spring 2.0.6+. |
| `mybatis.inject-sql-session-on-mapper-scan` | Set whether inject a `SqlSessionTemplate` or `SqlSessionFactory` bean (If you want to back to the behavior of 2.2.1 or before, specify `false`). If you use together with spring-native, should be set `true`(default). |
| `configuration.*` | Property keys for `Configuration` bean provided by MyBatis Core. About available nested properties see the [MyBatis reference page](http://www.mybatis.org/mybatis-3/configuration.html#settings). <span class="label important">NOTE</span>: This property cannot be used at the same time with the `config-location`. |
| `scripting-language-driver.thymeleaf.*` | Property keys for `ThymeleafLanguageDriverConfig` bean provided by MyBatis Thymeleaf. About available nested properties see the [MyBatis Thymeleaf reference page](http://www.mybatis.org/thymeleaf-scripting/user-guide.html#_configuration_properties). |
| `scripting-language-driver.freemarker.*` | Properties keys for `FreeMarkerLanguageDriverConfig` bean provided by MyBatis FreeMarker. About available nested properties see the [MyBatis FreeMarker reference page](http://www.mybatis.org/freemarker-scripting/#Configuration). This feature requires to use together with mybatis-freemarker 1.2.0+. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2021 the original author or authors.
* Copyright 2015-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -45,7 +45,7 @@ void testProperties() throws IOException {

List<Map<String, Object>> properties = documentContext.read("$.properties");

assertAll(() -> assertThat(properties.size()).isEqualTo(5), () -> {
assertAll(() -> assertThat(properties.size()).isEqualTo(6), () -> {
// assert for mybatis.configuration.default-scripting-language
Map<String, Object> element = properties.get(0);
assertThat(element.get("sourceType")).isEqualTo("org.apache.ibatis.session.Configuration");
Expand Down Expand Up @@ -78,8 +78,14 @@ void testProperties() throws IOException {
assertThat(element.get("name")).isEqualTo("mybatis.mapper-default-scope");
assertThat(element.get("type")).isEqualTo("java.lang.String");
}, () -> {
// assert for mybatis.scripting-language-driver.velocity.userdirective
// assert for mybatis.inject-sql-session-on-mapper-scan
Map<String, Object> element = properties.get(4);
assertThat(element.get("defaultValue")).isEqualTo(true);
assertThat(element.get("name")).isEqualTo("mybatis.inject-sql-session-on-mapper-scan");
assertThat(element.get("type")).isEqualTo("java.lang.Boolean");
}, () -> {
// assert for mybatis.scripting-language-driver.velocity.userdirective
Map<String, Object> element = properties.get(5);
assertThat(element.get("name")).isEqualTo("mybatis.scripting-language-driver.velocity.userdirective");
@SuppressWarnings("unchecked")
Map<String, Object> deprecation = (Map<String, Object>) element.get("deprecation");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2021 the original author or authors.
* Copyright 2015-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -75,6 +75,7 @@
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
Expand Down Expand Up @@ -183,6 +184,46 @@ void testScanWithLazy() {
assertThat(sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers()).hasSize(1);
}

@Test
void testAutoScanWithDefault() {
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisBootMapperScanAutoConfiguration.class,
MybatisAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SqlSessionFactory sqlSessionFactory = this.context.getBean(SqlSessionFactory.class);
assertThat(this.context.getBeanNamesForType(SqlSessionFactory.class)).hasSize(1);
assertThat(this.context.getBeanNamesForType(SqlSessionTemplate.class)).hasSize(1);
assertThat(this.context.getBeanNamesForType(CityMapper.class)).hasSize(1);
assertThat(this.context.getBean(SqlSessionTemplate.class).getExecutorType()).isEqualTo(ExecutorType.SIMPLE);
assertThat(this.context.getBean(SqlSessionFactory.class).getConfiguration().isMapUnderscoreToCamelCase()).isFalse();
this.context.getBean(CityMapper.class);
assertThat(sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers()).hasSize(1);
assertThat(((RuntimeBeanReference) this.context.getBeanDefinition("cityMapper").getPropertyValues()
.getPropertyValue("sqlSessionTemplate").getValue()).getBeanName()).isEqualTo("sqlSessionTemplate");
assertThat(
this.context.getBeanDefinition(this.context.getBeanNamesForType(MapperScannerConfigurer.class)[0]).getRole())
.isEqualTo(BeanDefinition.ROLE_INFRASTRUCTURE);
}

@Test
void testAutoScanWithInjectSqlSessionOnMapperScanIsFalse() {
TestPropertyValues.of("mybatis.inject-sql-session-on-mapper-scan:false").applyTo(this.context);
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisBootMapperScanAutoConfiguration.class,
MybatisAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SqlSessionFactory sqlSessionFactory = this.context.getBean(SqlSessionFactory.class);
assertThat(this.context.getBeanNamesForType(SqlSessionFactory.class)).hasSize(1);
assertThat(this.context.getBeanNamesForType(SqlSessionTemplate.class)).hasSize(1);
assertThat(this.context.getBeanNamesForType(CityMapper.class)).hasSize(1);
assertThat(this.context.getBean(SqlSessionTemplate.class).getExecutorType()).isEqualTo(ExecutorType.SIMPLE);
assertThat(this.context.getBean(SqlSessionFactory.class).getConfiguration().isMapUnderscoreToCamelCase()).isFalse();
this.context.getBean(CityMapper.class);
assertThat(sqlSessionFactory.getConfiguration().getMapperRegistry().getMappers()).hasSize(1);
assertThat(this.context.getBeanDefinition("cityMapper").getPropertyValues().getPropertyValue("sqlSessionTemplate"))
.isNull();
assertThat(this.context.getBeanDefinition("cityMapper").getPropertyValues().getPropertyValue("sqlSessionFactory"))
.isNull();
}

@Test
void testAutoScanWithLazy() {
TestPropertyValues.of("mybatis.lazy-initialization:true").applyTo(this.context);
Expand Down Expand Up @@ -601,12 +642,15 @@ void testWithConfigurationVariablesAndPropertiesSameKey() {

@Test
void testCustomSqlSessionFactory() {
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisAutoConfiguration.class,
CustomSqlSessionFactoryConfiguration.class);
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisBootMapperScanAutoConfiguration.class,
CustomSqlSessionFactoryConfiguration.class, MybatisAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(SqlSessionFactory.class)).hasSize(1);
assertThat(this.context.getBean(SqlSessionFactory.class).getConfiguration().getVariables().getProperty("key"))
.isEqualTo("value");
assertThat(this.context.getBeanNamesForType(CityMapper.class)).hasSize(1);
assertThat(((RuntimeBeanReference) this.context.getBeanDefinition("cityMapper").getPropertyValues()
.getPropertyValue("sqlSessionFactory").getValue()).getBeanName()).isEqualTo("customSqlSessionFactory");
}

@Test
Expand All @@ -620,11 +664,14 @@ void testMySqlSessionFactory() {

@Test
void testCustomSqlSessionTemplate() {
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisAutoConfiguration.class,
CustomSqlSessionTemplateConfiguration.class);
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisBootMapperScanAutoConfiguration.class,
CustomSqlSessionTemplateConfiguration.class, MybatisAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(SqlSessionTemplate.class)).hasSize(1);
assertThat(this.context.getBean(SqlSessionTemplate.class).getExecutorType()).isEqualTo(ExecutorType.BATCH);
assertThat(this.context.getBeanNamesForType(CityMapper.class)).hasSize(1);
assertThat(((RuntimeBeanReference) this.context.getBeanDefinition("cityMapper").getPropertyValues()
.getPropertyValue("sqlSessionTemplate").getValue()).getBeanName()).isEqualTo("customSqlSessionTemplate");
}

@Test
Expand All @@ -636,6 +683,19 @@ void testMySqlSessionTemplate() {
assertThat(this.context.getBean(SqlSessionTemplate.class)).isInstanceOf(MySqlSessionTemplate.class);
}

@Test
void testCustomSqlSessionTemplateAndSqlSessionFactory() {
this.context.register(EmbeddedDataSourceConfiguration.class, MybatisBootMapperScanAutoConfiguration.class,
CustomSqlSessionFactoryConfiguration.class, CustomSqlSessionTemplateConfiguration.class,
MybatisAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(SqlSessionTemplate.class)).hasSize(1);
assertThat(this.context.getBean(SqlSessionTemplate.class).getExecutorType()).isEqualTo(ExecutorType.BATCH);
assertThat(this.context.getBeanNamesForType(CityMapper.class)).hasSize(1);
assertThat(((RuntimeBeanReference) this.context.getBeanDefinition("cityMapper").getPropertyValues()
.getPropertyValue("sqlSessionTemplate").getValue()).getBeanName()).isEqualTo("customSqlSessionTemplate");
}

@Test
void testTypeAliasesSuperTypeIsSpecify() {
TestPropertyValues
Expand Down Expand Up @@ -965,7 +1025,7 @@ public VendorDatabaseIdProvider vendorDatabaseIdProvider(Properties vendorProper
@Configuration
static class CustomSqlSessionFactoryConfiguration {
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
public SqlSessionFactory customSqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
Properties props = new Properties();
Expand All @@ -989,7 +1049,7 @@ public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
@Configuration
static class CustomSqlSessionTemplateConfiguration {
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
public SqlSessionTemplate customSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
}
}
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2015-2021 the original author or authors.
Copyright 2015-2022 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -68,7 +68,7 @@

<properties>
<mybatis.version>3.5.9</mybatis.version>
<mybatis-spring.version>2.0.6</mybatis-spring.version>
<mybatis-spring.version>2.0.7-SNAPSHOT</mybatis-spring.version>
<mybatis-freemarker.version>1.2.3</mybatis-freemarker.version>
<mybatis-velocity.version>2.1.1</mybatis-velocity.version>
<mybatis-thymeleaf.version>1.0.3</mybatis-thymeleaf.version>
Expand Down