Skip to content

Use JdbcConnectionDetails to detect Dialect instead of Environment #294

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

Merged
merged 3 commits into from
Apr 26, 2025
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
5 changes: 5 additions & 0 deletions doma-spring-boot-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.seasar.doma.jdbc.dialect.StandardDialect;
import org.seasar.doma.jdbc.statistic.DefaultStatisticManager;
import org.seasar.doma.jdbc.statistic.StatisticManager;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
Expand All @@ -47,11 +48,11 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
Expand All @@ -76,39 +77,41 @@ public class DomaAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public Dialect dialect(Environment environment) {
public Dialect dialect(ObjectProvider<JdbcConnectionDetails> connectionDetailsProvider) {
DialectType dialectType = domaProperties.getDialect();
if (dialectType != null) {
return dialectType.create();
}
String url = environment.getProperty("spring.datasource.url");
if (url != null) {
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(url);
switch (databaseDriver) {
case DB2:
return new Db2Dialect();
case H2:
return new H2Dialect();
case HSQLDB:
return new HsqldbDialect();
case SQLSERVER:
case JTDS:
return new MssqlDialect();
case MYSQL:
return new MysqlDialect();
case ORACLE:
return new OracleDialect();
case POSTGRESQL:
return new PostgresDialect();
case SQLITE:
return new SqliteDialect();
default:
break;
}
JdbcConnectionDetails connectionDetails = connectionDetailsProvider.getIfAvailable();
if (connectionDetails == null) {
throw new BeanCreationException(
"No connection details available. You will probably have to set 'doma.dialect' explicitly.");
}
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(connectionDetails.getJdbcUrl());
switch (databaseDriver) {
case DB2:
return new Db2Dialect();
case H2:
return new H2Dialect();
case HSQLDB:
return new HsqldbDialect();
case SQLSERVER:
case JTDS:
return new MssqlDialect();
case MYSQL:
return new MysqlDialect();
case ORACLE:
return new OracleDialect();
case POSTGRESQL:
return new PostgresDialect();
case SQLITE:
return new SqliteDialect();
default:
break;
}
if (logger.isWarnEnabled()) {
logger.warn(
"StandardDialect was selected because no explicit configuration and it is not possible to guess from 'spring.datasource.url property'");
"StandardDialect was selected because no explicit configuration and it is not possible to guess from the connection details.");
}
return new StandardDialect();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.seasar.doma.boot.autoconfigure;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -49,15 +51,16 @@
import org.seasar.doma.jdbc.criteria.NativeSql;
import org.seasar.doma.jdbc.criteria.QueryDsl;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.H2Dialect;
import org.seasar.doma.jdbc.dialect.MysqlDialect;
import org.seasar.doma.jdbc.dialect.PostgresDialect;
import org.seasar.doma.jdbc.dialect.StandardDialect;
import org.seasar.doma.jdbc.statistic.DefaultStatisticManager;
import org.seasar.doma.jdbc.statistic.StatisticManager;
import org.seasar.doma.message.Message;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
Expand All @@ -69,6 +72,7 @@
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

public class DomaAutoConfigurationTest {
Expand Down Expand Up @@ -263,11 +267,71 @@ public void testDialectByDataSourceUrl() {
MutablePropertySources sources = context.getEnvironment()
.getPropertySources();
sources.addFirst(new MapPropertySource("test",
Collections.singletonMap("spring.datasource.url", "jdbc:h2:mem:example")));
Map.of("spring.datasource.url", "jdbc:postgresql://localhost:1234/example",
"doma.exception-translation-enabled",
"false" /* prevent database connections */)));
this.context.register(DomaAutoConfiguration.class, DataSourceAutoConfiguration.class);
this.context.refresh();
Dialect dialect = this.context.getBean(Dialect.class);
assertThat(dialect, is(instanceOf(H2Dialect.class)));
assertThat(dialect, is(instanceOf(PostgresDialect.class)));
}

@Test
public void testDialectByJdbConnectionDetails() {
MutablePropertySources sources = context.getEnvironment()
.getPropertySources();
sources.addFirst(new MapPropertySource("test",
Map.of("doma.exception-translation-enabled",
"false"/* prevent database connections */)));
this.context.register(DomaAutoConfiguration.class, DataSourceAutoConfiguration.class);
this.context.registerBean(JdbcConnectionDetails.class, () -> new JdbcConnectionDetails() {
@Override
public String getUsername() {
return "dummy";
}

@Override
public String getPassword() {
return "dummy";
}

@Override
public String getJdbcUrl() {
return "jdbc:postgresql://localhost:1234/example";
}
});
this.context.refresh();
Dialect dialect = this.context.getBean(Dialect.class);
assertThat(dialect, is(instanceOf(PostgresDialect.class)));
}

@Test
public void testDialectMissingJdbConnectionDetails() {
MutablePropertySources sources = context.getEnvironment()
.getPropertySources();
sources.addFirst(new MapPropertySource("test",
Map.of("doma.exception-translation-enabled",
"false"/* prevent database connections */)));
this.context.register(DomaAutoConfiguration.class, DataSourceAutoConfiguration.class);
this.context.registerBean(DataSource.class, SimpleDriverDataSource::new);
BeanCreationException exception = assertThrows(BeanCreationException.class,
() -> this.context.refresh());
assertThat(exception.getMessage(), containsString(
"No connection details available. You will probably have to set 'doma.dialect' explicitly."));
}

@Test
public void testDialectMissingJdbConnectionDetailsExplicitDialect() {
MutablePropertySources sources = context.getEnvironment()
.getPropertySources();
sources.addFirst(new MapPropertySource("test",
Map.of("doma.dialect", "POSTGRES", "doma.exception-translation-enabled",
"false"/* prevent database connections */)));
this.context.register(DomaAutoConfiguration.class, DataSourceAutoConfiguration.class);
this.context.registerBean(DataSource.class, SimpleDriverDataSource::new);
this.context.refresh();
Dialect dialect = this.context.getBean(Dialect.class);
assertThat(dialect, is(instanceOf(PostgresDialect.class)));
}

@Test
Expand Down