#368 - Use Spring R2DBC.

We now use Spring R2DBC DatabaseClient and utilities to implement Spring Data R2DBC functionality.

Original pull request: #412.
This commit is contained in:
Mark Paluch
2020-07-21 14:21:43 +02:00
parent f331572167
commit 086c5a1d2d
50 changed files with 535 additions and 1450 deletions

View File

@@ -32,13 +32,13 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.dao.DataAccessException;
import org.springframework.data.annotation.Id;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.testing.H2TestSupport;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@@ -70,9 +70,8 @@ public class H2IntegrationTests {
jdbc.execute("INSERT INTO legoset (id, name, manual) VALUES(42055, 'SCHAUFELRADBAGGER', 12)");
databaseClient.execute("SELECT COUNT(*) FROM legoset") //
.as(Long.class) //
.fetch() //
databaseClient.sql("SELECT COUNT(*) FROM legoset") //
.map(it -> it.get(0, Long.class)) //
.all() //
.as(StepVerifier::create) //
.expectNext(1L) //

View File

@@ -27,7 +27,7 @@ import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Tests for {@link AbstractR2dbcConfiguration}.

View File

@@ -1,488 +0,0 @@
/*
* Copyright 2019-2020 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.r2dbc.connectionfactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.*;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
import io.r2dbc.spi.Connection;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.IsolationLevel;
import io.r2dbc.spi.R2dbcBadGrammarException;
import io.r2dbc.spi.Statement;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.r2dbc.BadSqlGrammarException;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.reactive.TransactionSynchronization;
import org.springframework.transaction.reactive.TransactionSynchronizationManager;
import org.springframework.transaction.reactive.TransactionalOperator;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
* Unit tests for {@link R2dbcTransactionManager}.
*
* @author Mark Paluch
*/
public class R2dbcTransactionManagerUnitTests {
ConnectionFactory connectionFactoryMock = mock(ConnectionFactory.class);
Connection connectionMock = mock(Connection.class);
private R2dbcTransactionManager tm;
@Before
public void before() {
when(connectionFactoryMock.create()).thenReturn((Mono) Mono.just(connectionMock));
when(connectionMock.beginTransaction()).thenReturn(Mono.empty());
when(connectionMock.close()).thenReturn(Mono.empty());
tm = new R2dbcTransactionManager(connectionFactoryMock);
}
@Test // gh-107
public void testSimpleTransaction() {
TestTransactionSynchronization sync = new TestTransactionSynchronization(
TransactionSynchronization.STATUS_COMMITTED);
AtomicInteger commits = new AtomicInteger();
when(connectionMock.commitTransaction()).thenReturn(Mono.fromRunnable(commits::incrementAndGet));
TransactionalOperator operator = TransactionalOperator.create(tm);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).flatMap(it -> {
return TransactionSynchronizationManager.forCurrentTransaction()
.doOnNext(synchronizationManager -> synchronizationManager.registerSynchronization(sync));
}) //
.as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
assertThat(commits).hasValue(1);
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
assertThat(sync.beforeCommitCalled).isTrue();
assertThat(sync.afterCommitCalled).isTrue();
assertThat(sync.beforeCompletionCalled).isTrue();
assertThat(sync.afterCompletionCalled).isTrue();
}
@Test // gh-329
public void testBeginFails() {
reset(connectionFactoryMock);
when(connectionFactoryMock.create()).thenReturn(Mono.error(new R2dbcBadGrammarException("fail")));
when(connectionMock.rollbackTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectErrorSatisfies(actual -> {
assertThat(actual).isInstanceOf(CannotCreateTransactionException.class)
.hasCauseInstanceOf(BadSqlGrammarException.class);
}).verify();
}
@Test // gh-107
public void appliesIsolationLevel() {
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
when(connectionMock.getTransactionIsolationLevel()).thenReturn(IsolationLevel.READ_COMMITTED);
when(connectionMock.setTransactionIsolationLevel(any())).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(connectionMock).beginTransaction();
verify(connectionMock).setTransactionIsolationLevel(IsolationLevel.READ_COMMITTED);
verify(connectionMock).setTransactionIsolationLevel(IsolationLevel.SERIALIZABLE);
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
}
@Test // gh-184
public void doesNotSetIsolationLevelIfMatch() {
when(connectionMock.getTransactionIsolationLevel()).thenReturn(IsolationLevel.READ_COMMITTED);
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(connectionMock).beginTransaction();
verify(connectionMock, never()).setTransactionIsolationLevel(any());
verify(connectionMock).commitTransaction();
}
@Test // gh-184
public void doesNotSetAutoCommitDisabled() {
when(connectionMock.isAutoCommit()).thenReturn(false);
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(connectionMock).beginTransaction();
verify(connectionMock, never()).setAutoCommit(anyBoolean());
verify(connectionMock).commitTransaction();
}
@Test // gh-184
public void restoresAutoCommit() {
when(connectionMock.isAutoCommit()).thenReturn(true);
when(connectionMock.setAutoCommit(anyBoolean())).thenReturn(Mono.empty());
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(connectionMock).beginTransaction();
verify(connectionMock).setAutoCommit(false);
verify(connectionMock).setAutoCommit(true);
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
}
@Test // gh-107
public void appliesReadOnly() {
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
when(connectionMock.setTransactionIsolationLevel(any())).thenReturn(Mono.empty());
Statement statement = mock(Statement.class);
when(connectionMock.createStatement(anyString())).thenReturn(statement);
when(statement.execute()).thenReturn(Mono.empty());
tm.setEnforceReadOnly(true);
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setReadOnly(true);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).as(operator::transactional) //
.as(StepVerifier::create) //
.expectNextCount(1) //
.verifyComplete();
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).createStatement("SET TRANSACTION READ ONLY");
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
}
@Test // gh-107
public void testCommitFails() {
when(connectionMock.commitTransaction()).thenReturn(Mono.defer(() -> {
return Mono.error(new R2dbcBadGrammarException("Commit should fail"));
}));
when(connectionMock.rollbackTransaction()).thenReturn(Mono.empty());
TransactionalOperator operator = TransactionalOperator.create(tm);
ConnectionFactoryUtils.getConnection(connectionFactoryMock) //
.doOnNext(it -> {
it.createStatement("foo");
}).then() //
.as(operator::transactional) //
.as(StepVerifier::create) //
.verifyError(IllegalTransactionStateException.class);
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).createStatement("foo");
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
}
@Test // gh-107
public void testRollback() {
AtomicInteger commits = new AtomicInteger();
when(connectionMock.commitTransaction()).thenReturn(Mono.fromRunnable(commits::incrementAndGet));
AtomicInteger rollbacks = new AtomicInteger();
when(connectionMock.rollbackTransaction()).thenReturn(Mono.fromRunnable(rollbacks::incrementAndGet));
TransactionalOperator operator = TransactionalOperator.create(tm);
ConnectionFactoryUtils.getConnection(connectionFactoryMock).doOnNext(it -> {
throw new IllegalStateException();
}).as(operator::transactional) //
.as(StepVerifier::create) //
.verifyError(IllegalStateException.class);
assertThat(commits).hasValue(0);
assertThat(rollbacks).hasValue(1);
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).rollbackTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
}
@Test // gh-329
public void testRollbackFails() {
when(connectionMock.rollbackTransaction()).thenReturn(Mono.defer(() -> {
return Mono.error(new R2dbcBadGrammarException("Commit should fail"));
}), Mono.empty());
TransactionalOperator operator = TransactionalOperator.create(tm);
operator.execute(reactiveTransaction -> {
reactiveTransaction.setRollbackOnly();
return ConnectionFactoryUtils.getConnection(connectionFactoryMock) //
.doOnNext(it -> {
it.createStatement("foo");
}).then();
}).as(StepVerifier::create) //
.verifyError(IllegalTransactionStateException.class);
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).createStatement("foo");
verify(connectionMock, never()).commitTransaction();
verify(connectionMock).rollbackTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
}
@Test // gh-107
public void testTransactionSetRollbackOnly() {
when(connectionMock.rollbackTransaction()).thenReturn(Mono.empty());
TestTransactionSynchronization sync = new TestTransactionSynchronization(
TransactionSynchronization.STATUS_ROLLED_BACK);
TransactionalOperator operator = TransactionalOperator.create(tm);
operator.execute(tx -> {
tx.setRollbackOnly();
assertThat(tx.isNewTransaction()).isTrue();
return TransactionSynchronizationManager.forCurrentTransaction().doOnNext(it -> {
assertThat(it.hasResource(connectionFactoryMock)).isTrue();
it.registerSynchronization(sync);
}).then();
}).as(StepVerifier::create) //
.verifyComplete();
verify(connectionMock).isAutoCommit();
verify(connectionMock).beginTransaction();
verify(connectionMock).rollbackTransaction();
verify(connectionMock).close();
verifyNoMoreInteractions(connectionMock);
assertThat(sync.beforeCommitCalled).isFalse();
assertThat(sync.afterCommitCalled).isFalse();
assertThat(sync.beforeCompletionCalled).isTrue();
assertThat(sync.afterCompletionCalled).isTrue();
}
@Test // gh-107
public void testPropagationNeverWithExistingTransaction() {
when(connectionMock.rollbackTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
operator.execute(tx1 -> {
assertThat(tx1.isNewTransaction()).isTrue();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
return operator.execute(tx2 -> {
fail("Should have thrown IllegalTransactionStateException");
return Mono.empty();
});
}).as(StepVerifier::create) //
.verifyError(IllegalTransactionStateException.class);
verify(connectionMock).rollbackTransaction();
verify(connectionMock).close();
}
@Test // gh-107
public void testPropagationSupportsAndRequiresNew() {
when(connectionMock.commitTransaction()).thenReturn(Mono.empty());
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);
TransactionalOperator operator = TransactionalOperator.create(tm, definition);
operator.execute(tx1 -> {
assertThat(tx1.isNewTransaction()).isFalse();
DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition();
innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionalOperator inner = TransactionalOperator.create(tm, innerDef);
return inner.execute(tx2 -> {
assertThat(tx2.isNewTransaction()).isTrue();
return Mono.empty();
});
}).as(StepVerifier::create) //
.verifyComplete();
verify(connectionMock).commitTransaction();
verify(connectionMock).close();
}
private static class TestTransactionSynchronization implements TransactionSynchronization {
private int status;
public boolean beforeCommitCalled;
public boolean beforeCompletionCalled;
public boolean afterCommitCalled;
public boolean afterCompletionCalled;
public Throwable afterCompletionException;
public TestTransactionSynchronization(int status) {
this.status = status;
}
@Override
public Mono<Void> suspend() {
return Mono.empty();
}
@Override
public Mono<Void> resume() {
return Mono.empty();
}
@Override
public Mono<Void> beforeCommit(boolean readOnly) {
if (this.status != TransactionSynchronization.STATUS_COMMITTED) {
fail("Should never be called");
}
return Mono.fromRunnable(() -> {
assertFalse(this.beforeCommitCalled);
this.beforeCommitCalled = true;
});
}
@Override
public Mono<Void> beforeCompletion() {
return Mono.fromRunnable(() -> {
assertFalse(this.beforeCompletionCalled);
this.beforeCompletionCalled = true;
});
}
@Override
public Mono<Void> afterCommit() {
if (this.status != TransactionSynchronization.STATUS_COMMITTED) {
fail("Should never be called");
}
return Mono.fromRunnable(() -> {
assertFalse(this.afterCommitCalled);
this.afterCommitCalled = true;
});
}
@Override
public Mono<Void> afterCompletion(int status) {
try {
return Mono.fromRunnable(() -> doAfterCompletion(status));
} catch (Throwable ex) {
this.afterCompletionException = ex;
}
return Mono.empty();
}
protected void doAfterCompletion(int status) {
assertFalse(this.afterCompletionCalled);
this.afterCompletionCalled = true;
assertTrue(status == this.status);
}
}
}

View File

@@ -100,23 +100,6 @@ public class SingleConnectionConnectionFactoryUnitTests {
factory.destroy();
}
@Test // gh-204
public void releaseConnectionShouldNotCloseConnection() {
Connection connectionMock = mock(Connection.class);
ConnectionFactoryMetadata metadata = mock(ConnectionFactoryMetadata.class);
SingleConnectionConnectionFactory factory = new SingleConnectionConnectionFactory(connectionMock, metadata, false);
Connection connection = factory.create().block();
ConnectionFactoryUtils.releaseConnection(connection, factory) //
.as(StepVerifier::create) //
.verifyComplete();
verify(connectionMock, never()).close();
}
@Test // gh-204
public void releaseConnectionShouldCloseUnrelatedConnection() {

View File

@@ -37,9 +37,9 @@ import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.r2dbc.mapping.OutboundRow;
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.r2dbc.core.Parameter;
/**
* Unit tests for {@link MappingR2dbcConverter}.
@@ -72,12 +72,12 @@ public class MappingR2dbcConverterUnitTests {
LocalDateTime localDateTime = LocalDateTime.now();
converter.write(new Person("id", "Walter", "White", instant, localDateTime), row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("id"), SettableValue.fromOrEmpty("id", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("id"), Parameter.fromOrEmpty("id", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("firstname"),
SettableValue.fromOrEmpty("Walter", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("lastname"), SettableValue.fromOrEmpty("White", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("instant"), SettableValue.from(instant));
assertThat(row).containsEntry(SqlIdentifier.unquoted("local_date_time"), SettableValue.from(localDateTime));
Parameter.fromOrEmpty("Walter", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("lastname"), Parameter.fromOrEmpty("White", String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("instant"), Parameter.from(instant));
assertThat(row).containsEntry(SqlIdentifier.unquoted("local_date_time"), Parameter.from(localDateTime));
}
@Test // gh-41
@@ -117,7 +117,7 @@ public class MappingR2dbcConverterUnitTests {
OutboundRow row = new OutboundRow();
converter.write(withMap, row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("nested"), SettableValue.from("map"));
assertThat(row).containsEntry(SqlIdentifier.unquoted("nested"), Parameter.from("map"));
}
@Test // gh-59
@@ -138,7 +138,7 @@ public class MappingR2dbcConverterUnitTests {
OutboundRow row = new OutboundRow();
converter.write(withMap, row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("condition"), SettableValue.from("Mint"));
assertThat(row).containsEntry(SqlIdentifier.unquoted("condition"), Parameter.from("Mint"));
}
@Test // gh-59
@@ -148,7 +148,7 @@ public class MappingR2dbcConverterUnitTests {
OutboundRow row = new OutboundRow();
converter.write(withMap, row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("condition"), SettableValue.fromOrEmpty(null, String.class));
assertThat(row).containsEntry(SqlIdentifier.unquoted("condition"), Parameter.fromOrEmpty(null, String.class));
}
@Test // gh-59
@@ -172,8 +172,8 @@ public class MappingR2dbcConverterUnitTests {
OutboundRow row = new OutboundRow();
converter.write(person, row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("foo_column"), SettableValue.from("bar"))
.containsEntry(SqlIdentifier.unquoted("entity"), SettableValue.from("nested_entity"));
assertThat(row).containsEntry(SqlIdentifier.unquoted("foo_column"), Parameter.from("bar"))
.containsEntry(SqlIdentifier.unquoted("entity"), Parameter.from("nested_entity"));
}
@Test // gh-59
@@ -263,8 +263,8 @@ public class MappingR2dbcConverterUnitTests {
public OutboundRow convert(CustomConversionPerson source) {
OutboundRow row = new OutboundRow();
row.put("foo_column", SettableValue.from(source.foo));
row.put("entity", SettableValue.from("nested_entity"));
row.put("foo_column", Parameter.from(source.foo));
row.put("entity", Parameter.from("nested_entity"));
return row;
}

View File

@@ -32,9 +32,9 @@ import org.springframework.data.convert.CustomConversions;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.OutboundRow;
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.r2dbc.core.Parameter;
/**
* Postgres-specific unit tests for {@link MappingR2dbcConverter}.
@@ -69,7 +69,7 @@ public class PostgresMappingR2dbcConverterUnitTests {
OutboundRow row = new OutboundRow();
converter.write(person, row);
assertThat(row).containsEntry(SqlIdentifier.unquoted("json_value"), SettableValue.from(person.jsonValue));
assertThat(row).containsEntry(SqlIdentifier.unquoted("json_value"), Parameter.from(person.jsonValue));
}
@AllArgsConstructor

View File

@@ -36,9 +36,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.r2dbc.connection.R2dbcTransactionManager;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
@@ -146,7 +147,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
public void executeInsertInManagedTransaction() {
Flux<Integer> integerFlux = databaseClient //
.execute(getInsertIntoLegosetStatement()) //
.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //
@@ -162,7 +163,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
@Test // gh-2
public void executeInsertInAutoCommitTransaction() {
Flux<Integer> integerFlux = databaseClient.execute(getInsertIntoLegosetStatement()) //
Flux<Integer> integerFlux = databaseClient.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //
@@ -178,7 +179,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
@Test // gh-2
public void shouldRollbackTransaction() {
Mono<Object> integerFlux = databaseClient.execute(getInsertIntoLegosetStatement()) //
Mono<Object> integerFlux = databaseClient.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //
@@ -196,7 +197,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
@Test // gh-2, gh-75, gh-107
public void emitTransactionIds() {
Flux<Object> txId = databaseClient.execute(getCurrentTransactionIdStatement()) //
Flux<Object> txId = databaseClient.sql(getCurrentTransactionIdStatement()) //
.map((row, md) -> row.get(0)) //
.all();
@@ -220,7 +221,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
TransactionalOperator transactionalOperator = TransactionalOperator
.create(new R2dbcTransactionManager(connectionFactory), new DefaultTransactionDefinition());
Flux<Integer> integerFlux = databaseClient.execute(getInsertIntoLegosetStatement()) //
Flux<Integer> integerFlux = databaseClient.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //
@@ -301,7 +302,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
@Transactional
public Flux<Object> emitTransactionIds(Mono<Void> prepareTransaction, String idStatement) {
Flux<Object> txId = databaseClient.execute(idStatement) //
Flux<Object> txId = databaseClient.sql(idStatement) //
.map((row, md) -> row.get(0)) //
.all();
@@ -311,7 +312,7 @@ public abstract class AbstractTransactionalDatabaseClientIntegrationTests extend
@Transactional
public Flux<Integer> shouldRollbackTransactionUsingTransactionalOperator(String insertStatement) {
return databaseClient.execute(insertStatement) //
return databaseClient.sql(insertStatement) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //

View File

@@ -26,6 +26,7 @@ import org.junit.ClassRule;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Transactional integration tests for {@link DatabaseClient} against MySQL using Jasync MySQL.
@@ -62,7 +63,7 @@ public class JasyncMySqlTransactionalDatabaseClientIntegrationTests
* batches every now and then.
* @see: https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-internal-data.html
*/
return client.execute(getInsertIntoLegosetStatement()) //
return client.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //

View File

@@ -26,6 +26,7 @@ import org.junit.ClassRule;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MariaDbTestSupport;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Transactional integration tests for {@link DatabaseClient} against MariaDb.
@@ -61,7 +62,7 @@ public class MariaDbTransactionalDatabaseClientIntegrationTests
* And we need to delay emitting the result so that Mariadb has time to write the transaction id, which is done in
* batches every now and then.
*/
return client.execute(getInsertIntoLegosetStatement()) //
return client.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //

View File

@@ -26,6 +26,7 @@ import org.junit.ClassRule;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.MySqlTestSupport;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Transactional integration tests for {@link DatabaseClient} against MySQL.
@@ -62,7 +63,7 @@ public class MySqlTransactionalDatabaseClientIntegrationTests
* batches every now and then.
* @see: https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-internal-data.html
*/
return client.execute(getInsertIntoLegosetStatement()) //
return client.sql(getInsertIntoLegosetStatement()) //
.bind(0, 42055) //
.bind(1, "SCHAUFELRADBAGGER") //
.bindNull(2, Integer.class) //

View File

@@ -33,6 +33,7 @@ import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.OutboundRow;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.r2dbc.core.Parameter;
/**
* {@link PostgresDialect} specific tests for {@link ReactiveDataAccessStrategy}.
@@ -88,8 +89,8 @@ public class PostgresReactiveDataAccessStrategyTests extends ReactiveDataAccessS
OutboundRow outboundRow = strategy.getOutboundRow(withArray);
assertThat(outboundRow) //
.containsEntry(SqlIdentifier.unquoted("string_array"), SettableValue.from(new String[] { "hello", "world" }))
.containsEntry(SqlIdentifier.unquoted("string_list"), SettableValue.from(new String[] { "hello", "world" }));
.containsEntry(SqlIdentifier.unquoted("string_array"), Parameter.from(new String[] { "hello", "world" }))
.containsEntry(SqlIdentifier.unquoted("string_list"), Parameter.from(new String[] { "hello", "world" }));
}
@Test // gh-139
@@ -104,7 +105,7 @@ public class PostgresReactiveDataAccessStrategyTests extends ReactiveDataAccessS
OutboundRow outboundRow = strategy.getOutboundRow(withConversion);
assertThat(outboundRow) //
.containsEntry(SqlIdentifier.unquoted("my_objects"), SettableValue.from("[one, two]"));
.containsEntry(SqlIdentifier.unquoted("my_objects"), Parameter.from("[one, two]"));
}
@Test // gh-139
@@ -121,7 +122,7 @@ public class PostgresReactiveDataAccessStrategyTests extends ReactiveDataAccessS
assertThat(outboundRow) //
.containsKey(SqlIdentifier.unquoted("my_objects"));
SettableValue value = outboundRow.get("my_objects");
Parameter value = outboundRow.get("my_objects");
assertThat(value.isEmpty()).isTrue();
assertThat(value.getType()).isEqualTo(String.class);
}
@@ -139,7 +140,7 @@ public class PostgresReactiveDataAccessStrategyTests extends ReactiveDataAccessS
assertThat(outboundRow).containsKey(SqlIdentifier.unquoted("enum_set"));
SettableValue value = outboundRow.get(SqlIdentifier.unquoted("enum_set"));
Parameter value = outboundRow.get(SqlIdentifier.unquoted("enum_set"));
assertThat(value.getValue()).isEqualTo(new String[] { "ONE", "TWO" });
}
@@ -156,7 +157,7 @@ public class PostgresReactiveDataAccessStrategyTests extends ReactiveDataAccessS
assertThat(outboundRow).containsKey(SqlIdentifier.unquoted("enum_array"));
SettableValue value = outboundRow.get(SqlIdentifier.unquoted("enum_array"));
Parameter value = outboundRow.get(SqlIdentifier.unquoted("enum_array"));
assertThat(value.getValue()).isEqualTo(new String[] { "ONE", "TWO" });
}

View File

@@ -40,7 +40,6 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.callback.ReactiveEntityCallbacks;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.OutboundRow;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.r2dbc.mapping.event.AfterConvertCallback;
import org.springframework.data.r2dbc.mapping.event.AfterSaveCallback;
import org.springframework.data.r2dbc.mapping.event.BeforeConvertCallback;
@@ -52,6 +51,8 @@ import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.lang.Nullable;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.Parameter;
import org.springframework.util.CollectionUtils;
/**
@@ -61,7 +62,7 @@ import org.springframework.util.CollectionUtils;
*/
public class R2dbcEntityTemplateUnitTests {
DatabaseClient client;
org.springframework.r2dbc.core.DatabaseClient client;
R2dbcEntityTemplate entityTemplate;
StatementRecorder recorder;
@@ -70,8 +71,8 @@ public class R2dbcEntityTemplateUnitTests {
recorder = StatementRecorder.newInstance();
client = DatabaseClient.builder().connectionFactory(recorder)
.dataAccessStrategy(new DefaultReactiveDataAccessStrategy(PostgresDialect.INSTANCE)).build();
entityTemplate = new R2dbcEntityTemplate(client);
.bindMarkers(PostgresDialect.INSTANCE.getBindMarkersFactory()).build();
entityTemplate = new R2dbcEntityTemplate(client, PostgresDialect.INSTANCE);
}
@Test // gh-220
@@ -92,7 +93,7 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
assertThat(statement.getSql()).isEqualTo("SELECT COUNT(person.id) FROM person WHERE person.THE_NAME = $1");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220
@@ -113,7 +114,7 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
assertThat(statement.getSql()).isEqualTo("SELECT person.id FROM person WHERE person.THE_NAME = $1 LIMIT 1");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220
@@ -129,7 +130,7 @@ public class R2dbcEntityTemplateUnitTests {
assertThat(statement.getSql())
.isEqualTo("SELECT person.* FROM person WHERE person.THE_NAME = $1 ORDER BY THE_NAME ASC");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-215
@@ -170,7 +171,7 @@ public class R2dbcEntityTemplateUnitTests {
assertThat(statement.getSql())
.isEqualTo("SELECT person.* FROM person WHERE person.THE_NAME = $1 ORDER BY THE_NAME ASC LIMIT 2");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220
@@ -191,8 +192,8 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("UPDATE"));
assertThat(statement.getSql()).isEqualTo("UPDATE person SET THE_NAME = $1 WHERE person.THE_NAME = $2");
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, SettableValue.from("Heisenberg")).containsEntry(1,
SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, Parameter.from("Heisenberg")).containsEntry(1,
Parameter.from("Walter"));
}
@Test // gh-220
@@ -212,7 +213,7 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("DELETE"));
assertThat(statement.getSql()).isEqualTo("DELETE FROM person WHERE person.THE_NAME = $1");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220
@@ -229,7 +230,7 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("DELETE"));
assertThat(statement.getSql()).isEqualTo("DELETE FROM person WHERE person.id = $1");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-365
@@ -249,8 +250,8 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("INSERT"));
assertThat(statement.getSql()).isEqualTo("INSERT INTO versioned_person (id, version, name) VALUES ($1, $2, $3)");
assertThat(statement.getBindings()).hasSize(3).containsEntry(0, SettableValue.from("id")).containsEntry(1,
SettableValue.from(1L));
assertThat(statement.getBindings()).hasSize(3).containsEntry(0, Parameter.from("id")).containsEntry(1,
Parameter.from(1L));
}
@Test // gh-215
@@ -277,8 +278,8 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("INSERT"));
assertThat(statement.getSql()).isEqualTo("INSERT INTO person (THE_NAME, description) VALUES ($1, $2)");
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, SettableValue.from("before-convert"))
.containsEntry(1, SettableValue.from("before-save"));
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, Parameter.from("before-convert")).containsEntry(1,
Parameter.from("before-save"));
}
@Test // gh-365
@@ -299,8 +300,8 @@ public class R2dbcEntityTemplateUnitTests {
assertThat(statement.getSql()).isEqualTo(
"UPDATE versioned_person SET version = $1, name = $2 WHERE versioned_person.id = $3 AND (versioned_person.version = $4)");
assertThat(statement.getBindings()).hasSize(4).containsEntry(0, SettableValue.from(2L)).containsEntry(3,
SettableValue.from(1L));
assertThat(statement.getBindings()).hasSize(4).containsEntry(0, Parameter.from(2L)).containsEntry(3,
Parameter.from(1L));
}
@Test // gh-215
@@ -332,8 +333,8 @@ public class R2dbcEntityTemplateUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("UPDATE"));
assertThat(statement.getSql()).isEqualTo("UPDATE person SET THE_NAME = $1, description = $2 WHERE person.id = $3");
assertThat(statement.getBindings()).hasSize(3).containsEntry(0, SettableValue.from("before-convert"))
.containsEntry(1, SettableValue.from("before-save"));
assertThat(statement.getBindings()).hasSize(3).containsEntry(0, Parameter.from("before-convert")).containsEntry(1,
Parameter.from("before-save"));
}
@ToString
@@ -402,7 +403,7 @@ public class R2dbcEntityTemplateUnitTests {
public Mono<Person> onBeforeSave(Person entity, OutboundRow outboundRow, SqlIdentifier table) {
capture(entity);
outboundRow.put(SqlIdentifier.unquoted("description"), SettableValue.from("before-save"));
outboundRow.put(SqlIdentifier.unquoted("description"), Parameter.from("before-save"));
return Mono.just(entity);
}
}

View File

@@ -38,8 +38,8 @@ import org.junit.Test;
import org.springframework.data.annotation.ReadOnlyProperty;
import org.springframework.data.r2dbc.dialect.R2dbcDialect;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.r2dbc.core.Parameter;
/**
* Abstract base class for {@link R2dbcDialect}-aware {@link DefaultReactiveDataAccessStrategy} tests.
@@ -205,7 +205,7 @@ public abstract class ReactiveDataAccessStrategyTestSupport {
setter.accept(toSave, testValue);
assertThat(strategy.getOutboundRow(toSave)).containsEntry(SqlIdentifier.unquoted(fieldname),
SettableValue.from(testValue));
Parameter.from(testValue));
when(rowMock.get(fieldname)).thenReturn(testValue);

View File

@@ -30,6 +30,7 @@ import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.r2dbc.testing.StatementRecorder;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.r2dbc.core.Parameter;
/**
* Unit test for {@link ReactiveDeleteOperation}.
@@ -104,7 +105,7 @@ public class ReactiveDeleteOperationUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("DELETE"));
assertThat(statement.getSql()).isEqualTo("DELETE FROM person WHERE person.THE_NAME = $1");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220

View File

@@ -31,6 +31,7 @@ import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.r2dbc.testing.StatementRecorder;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.r2dbc.core.Parameter;
/**
* Unit test for {@link ReactiveInsertOperation}.
@@ -77,7 +78,7 @@ public class ReactiveInsertOperationUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("INSERT"));
assertThat(statement.getSql()).isEqualTo("INSERT INTO person (THE_NAME) VALUES ($1)");
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
}
@Test // gh-220

View File

@@ -27,10 +27,10 @@ import org.junit.Test;
import org.springframework.data.annotation.Id;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.data.r2dbc.testing.StatementRecorder;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.query.Update;
import org.springframework.r2dbc.core.Parameter;
/**
* Unit test for {@link ReactiveUpdateOperation}.
@@ -107,8 +107,8 @@ public class ReactiveUpdateOperationUnitTests {
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("UPDATE"));
assertThat(statement.getSql()).isEqualTo("UPDATE person SET THE_NAME = $1 WHERE person.THE_NAME = $2");
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, SettableValue.from("Heisenberg")).containsEntry(1,
SettableValue.from("Walter"));
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, Parameter.from("Heisenberg")).containsEntry(1,
Parameter.from("Walter"));
}
@Test // gh-220

View File

@@ -49,6 +49,7 @@ import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.testing.H2TestSupport;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.r2dbc.core.Parameter;
import org.springframework.test.context.junit4.SpringRunner;
/**
@@ -149,10 +150,10 @@ public class ConvertingR2dbcRepositoryIntegrationTests {
OutboundRow outboundRow = new OutboundRow();
if (convertedEntity.getId() != null) {
outboundRow.put("id", SettableValue.from(convertedEntity.getId()));
outboundRow.put("id", Parameter.from(convertedEntity.getId()));
}
outboundRow.put("name", SettableValue.from("prefixed: " + convertedEntity.getName()));
outboundRow.put("name", Parameter.from("prefixed: " + convertedEntity.getName()));
return outboundRow;
}

View File

@@ -26,13 +26,13 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.dialect.MySqlDialect;
import org.springframework.data.r2dbc.dialect.PostgresDialect;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.dialect.SqlServerDialect;
import org.springframework.data.r2dbc.repository.config.mysql.MySqlPersonRepository;
import org.springframework.data.r2dbc.repository.config.sqlserver.SqlServerPersonRepository;

View File

@@ -38,7 +38,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.annotation.Id;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.r2dbc.convert.R2dbcConverter;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.DefaultReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.dialect.DialectResolver;
@@ -88,8 +88,7 @@ public class PartTreeR2dbcQueryUnitTests {
R2dbcDialect dialect = DialectResolver.getDialect(connectionFactory);
dataAccessStrategy = new DefaultReactiveDataAccessStrategy(dialect, r2dbcConverter);
databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory)
.dataAccessStrategy(dataAccessStrategy).build();
databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory).build();
}
@Test // gh-282
@@ -166,7 +165,7 @@ public class PartTreeR2dbcQueryUnitTests {
assertThat(bindableQuery.get())
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".date_of_birth BETWEEN $1 AND $2");
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
when(bindSpecMock.bind(anyInt(), any())).thenReturn(bindSpecMock);
bindableQuery.bind(bindSpecMock);
@@ -325,7 +324,7 @@ public class PartTreeR2dbcQueryUnitTests {
dataAccessStrategy);
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "Jo" });
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
bindableQuery.bind(bindSpecMock);
verify(bindSpecMock, times(1)).bind(0, "Jo%");
@@ -353,7 +352,7 @@ public class PartTreeR2dbcQueryUnitTests {
dataAccessStrategy);
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "hn" });
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
bindableQuery.bind(bindSpecMock);
verify(bindSpecMock, times(1)).bind(0, "%hn");
@@ -381,7 +380,7 @@ public class PartTreeR2dbcQueryUnitTests {
dataAccessStrategy);
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
bindableQuery.bind(bindSpecMock);
verify(bindSpecMock, times(1)).bind(0, "%oh%");
@@ -409,7 +408,7 @@ public class PartTreeR2dbcQueryUnitTests {
dataAccessStrategy);
RelationalParametersParameterAccessor accessor = getAccessor(queryMethod, new Object[] { "oh" });
BindableQuery bindableQuery = r2dbcQuery.createQuery(accessor);
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
bindableQuery.bind(bindSpecMock);
verify(bindSpecMock, times(1)).bind(0, "%oh%");

View File

@@ -23,11 +23,14 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.PreparedOperation;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.PreparedOperation;
/**
* Unit tests for {@link PreparedOperationBindableQuery}.
*
* @author Roman Chigvintsev
* @author Marl Paluch
*/
@RunWith(MockitoJUnitRunner.class)
@Ignore
@@ -35,11 +38,10 @@ public class PreparedOperationBindableQueryUnitTests {
@Mock PreparedOperation<?> preparedOperation;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test // gh-282
public void bindsQueryParameterValues() {
DatabaseClient.BindSpec bindSpecMock = mock(DatabaseClient.BindSpec.class);
DatabaseClient.GenericExecuteSpec bindSpecMock = mock(DatabaseClient.GenericExecuteSpec.class);
PreparedOperationBindableQuery query = new PreparedOperationBindableQuery(preparedOperation);
query.bind(bindSpecMock);

View File

@@ -32,8 +32,8 @@ import org.springframework.data.geo.Point;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.DatabaseClient.GenericExecuteSpec;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.r2dbc.core.DatabaseClient.GenericExecuteSpec;
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;

View File

@@ -41,7 +41,6 @@ import org.springframework.data.annotation.Version;
import org.springframework.data.domain.Persistable;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
@@ -50,6 +49,7 @@ import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
import org.springframework.data.relational.repository.support.MappingRelationalEntityInformation;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Abstract integration tests for {@link SimpleR2dbcRepository} to be ran against various databases.

View File

@@ -27,12 +27,12 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.annotation.Id;
import org.springframework.data.r2dbc.convert.MappingR2dbcConverter;
import org.springframework.data.r2dbc.convert.R2dbcConverter;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.mapping.R2dbcMappingContext;
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
import org.springframework.data.relational.repository.support.MappingRelationalEntityInformation;
import org.springframework.data.repository.Repository;
import org.springframework.r2dbc.core.DatabaseClient;
/**
* Unit test for {@link R2dbcRepositoryFactory}.

View File

@@ -40,7 +40,7 @@ import java.util.regex.Pattern;
import org.reactivestreams.Publisher;
import org.springframework.data.r2dbc.mapping.SettableValue;
import org.springframework.r2dbc.core.Parameter;
/**
* Recorder utility for R2DBC {@link Statement}s. Allows stubbing and introspection.
@@ -255,7 +255,7 @@ public class StatementRecorder implements ConnectionFactory {
private final List<Result> results;
private final Map<Object, SettableValue> bindings = new LinkedHashMap<>();
private final Map<Object, Parameter> bindings = new LinkedHashMap<>();
public RecordedStatement(String sql, Result result) {
this(sql, Collections.singletonList(result));
@@ -266,7 +266,7 @@ public class StatementRecorder implements ConnectionFactory {
this.results = results;
}
public Map<Object, SettableValue> getBindings() {
public Map<Object, Parameter> getBindings() {
return bindings;
}
@@ -281,25 +281,25 @@ public class StatementRecorder implements ConnectionFactory {
@Override
public Statement bind(int index, Object o) {
this.bindings.put(index, SettableValue.from(o));
this.bindings.put(index, Parameter.from(o));
return this;
}
@Override
public Statement bind(String identifier, Object o) {
this.bindings.put(identifier, SettableValue.from(o));
this.bindings.put(identifier, Parameter.from(o));
return this;
}
@Override
public Statement bindNull(int index, Class<?> type) {
this.bindings.put(index, SettableValue.empty(type));
this.bindings.put(index, Parameter.empty(type));
return this;
}
@Override
public Statement bindNull(String identifier, Class<?> type) {
this.bindings.put(identifier, SettableValue.empty(type));
this.bindings.put(identifier, Parameter.empty(type));
return this;
}