#104 - Provide extension mechanism for R2dbcDialect resolution.
We now use Spring's spring.factories mechanism to register and lookup R2dbcDialectProvider implementations. This allows a pluggable model for third party implementations to ship R2dbcDialect support that can be auto-discovered. Original pull request: #127.
This commit is contained in:
@@ -1,56 +0,0 @@
|
||||
package org.springframework.data.r2dbc.dialect;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import io.r2dbc.h2.H2ConnectionConfiguration;
|
||||
import io.r2dbc.h2.H2ConnectionFactory;
|
||||
import io.r2dbc.mssql.MssqlConnectionConfiguration;
|
||||
import io.r2dbc.mssql.MssqlConnectionFactory;
|
||||
import io.r2dbc.postgresql.PostgresqlConnectionConfiguration;
|
||||
import io.r2dbc.postgresql.PostgresqlConnectionFactory;
|
||||
import io.r2dbc.spi.Connection;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryMetadata;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Database}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DatabaseUnitTests {
|
||||
|
||||
@Test // gh-20
|
||||
public void shouldResolveDatabaseType() {
|
||||
|
||||
PostgresqlConnectionFactory postgres = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
|
||||
.host("localhost").database("foo").username("bar").password("password").build());
|
||||
MssqlConnectionFactory mssql = new MssqlConnectionFactory(MssqlConnectionConfiguration.builder().host("localhost")
|
||||
.database("foo").username("bar").password("password").build());
|
||||
H2ConnectionFactory h2 = new H2ConnectionFactory(H2ConnectionConfiguration.builder().inMemory("mem").build());
|
||||
|
||||
assertThat(Database.findDatabase(postgres)).contains(Database.POSTGRES);
|
||||
assertThat(Database.findDatabase(mssql)).contains(Database.SQL_SERVER);
|
||||
assertThat(Database.findDatabase(h2)).contains(Database.H2);
|
||||
}
|
||||
|
||||
@Test // gh-20
|
||||
public void shouldNotResolveUnknownDatabase() {
|
||||
assertThat(Database.findDatabase(new UnknownConnectionFactory())).isEmpty();
|
||||
}
|
||||
|
||||
static class UnknownConnectionFactory implements ConnectionFactory {
|
||||
|
||||
@Override
|
||||
public Publisher<? extends Connection> create() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionFactoryMetadata getMetadata() {
|
||||
return () -> "foo";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package org.springframework.data.r2dbc.dialect;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import io.r2dbc.h2.H2ConnectionConfiguration;
|
||||
import io.r2dbc.h2.H2ConnectionFactory;
|
||||
import io.r2dbc.mssql.MssqlConnectionConfiguration;
|
||||
import io.r2dbc.mssql.MssqlConnectionFactory;
|
||||
import io.r2dbc.postgresql.PostgresqlConnectionConfiguration;
|
||||
import io.r2dbc.postgresql.PostgresqlConnectionFactory;
|
||||
import io.r2dbc.spi.Connection;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryMetadata;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
|
||||
import org.springframework.data.relational.core.dialect.LimitClause;
|
||||
import org.springframework.data.relational.core.sql.render.SelectRenderContext;
|
||||
|
||||
import com.github.jasync.r2dbc.mysql.JasyncConnectionFactory;
|
||||
import com.github.jasync.sql.db.mysql.pool.MySQLConnectionFactory;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DialectResolver}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DialectResolverUnitTests {
|
||||
|
||||
@Test // gh-20, gh-104
|
||||
public void shouldResolveDatabaseType() {
|
||||
|
||||
PostgresqlConnectionFactory postgres = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
|
||||
.host("localhost").database("foo").username("bar").password("password").build());
|
||||
MssqlConnectionFactory mssql = new MssqlConnectionFactory(MssqlConnectionConfiguration.builder().host("localhost")
|
||||
.database("foo").username("bar").password("password").build());
|
||||
H2ConnectionFactory h2 = new H2ConnectionFactory(H2ConnectionConfiguration.builder().inMemory("mem").build());
|
||||
JasyncConnectionFactory mysql = new JasyncConnectionFactory(mock(MySQLConnectionFactory.class));
|
||||
|
||||
assertThat(DialectResolver.getDialect(postgres)).isEqualTo(PostgresDialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(mssql)).isEqualTo(SqlServerDialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(h2)).isEqualTo(H2Dialect.INSTANCE);
|
||||
assertThat(DialectResolver.getDialect(mysql)).isEqualTo(MySqlDialect.INSTANCE);
|
||||
}
|
||||
|
||||
@Test // gh-20, gh-104
|
||||
public void shouldNotResolveUnknownDatabase() {
|
||||
assertThatThrownBy(() -> DialectResolver.getDialect(new ExternalConnectionFactory("unknown")))
|
||||
.isInstanceOf(DialectResolver.NoDialectException.class);
|
||||
}
|
||||
|
||||
@Test // gh-104
|
||||
public void shouldResolveExternalDialect() {
|
||||
assertThat(DialectResolver.getDialect(new ExternalConnectionFactory("external")))
|
||||
.isEqualTo(ExternalDialect.INSTANCE);
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
static class ExternalConnectionFactory implements ConnectionFactory {
|
||||
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public Publisher<? extends Connection> create() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionFactoryMetadata getMetadata() {
|
||||
return () -> this.name;
|
||||
}
|
||||
}
|
||||
|
||||
static class ExternalDialectProvider implements DialectResolver.R2dbcDialectProvider {
|
||||
|
||||
@Override
|
||||
public Optional<R2dbcDialect> getDialect(ConnectionFactory connectionFactory) {
|
||||
|
||||
if (connectionFactory.getMetadata().getName().equals("external")) {
|
||||
return Optional.of(ExternalDialect.INSTANCE);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
enum ExternalDialect implements R2dbcDialect {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public BindMarkersFactory getBindMarkersFactory() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LimitClause limit() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectRenderContext getSelectContext() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,8 @@ import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
|
||||
import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy;
|
||||
import org.springframework.data.r2dbc.core.TransactionalDatabaseClient;
|
||||
import org.springframework.data.r2dbc.dialect.Database;
|
||||
import org.springframework.data.r2dbc.dialect.DialectResolver;
|
||||
import org.springframework.data.r2dbc.dialect.R2dbcDialect;
|
||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
@@ -172,9 +173,9 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
@Test
|
||||
public void shouldInsertItemsTransactional() {
|
||||
|
||||
Database database = Database.findDatabase(createConnectionFactory()).get();
|
||||
DefaultReactiveDataAccessStrategy dataAccessStrategy = new DefaultReactiveDataAccessStrategy(
|
||||
database.defaultDialect(), new MappingR2dbcConverter(mappingContext));
|
||||
R2dbcDialect dialect = DialectResolver.getDialect(createConnectionFactory());
|
||||
DefaultReactiveDataAccessStrategy dataAccessStrategy = new DefaultReactiveDataAccessStrategy(dialect,
|
||||
new MappingR2dbcConverter(mappingContext));
|
||||
TransactionalDatabaseClient client = TransactionalDatabaseClient.builder()
|
||||
.connectionFactory(createConnectionFactory()).dataAccessStrategy(dataAccessStrategy).build();
|
||||
|
||||
|
||||
1
src/test/resources/META-INF/spring.factories
Normal file
1
src/test/resources/META-INF/spring.factories
Normal file
@@ -0,0 +1 @@
|
||||
org.springframework.data.r2dbc.dialect.DialectResolver$R2dbcDialectProvider=org.springframework.data.r2dbc.dialect.DialectResolverUnitTests.ExternalDialectProvider
|
||||
Reference in New Issue
Block a user