#89 - Accept SQL directly in DatabaseClient.execute(…) stage.

We compressed client.execute().sql(…) to client.execute(…) to not require the intermediate execute() step but rather accept the SQL to execute directly.

Original pull request: #112.
This commit is contained in:
Mark Paluch
2019-05-06 15:06:56 +02:00
parent 36c4c1d062
commit 8b77aa9431
10 changed files with 83 additions and 42 deletions

View File

@@ -46,8 +46,41 @@ import org.springframework.data.r2dbc.support.R2dbcExceptionTranslator;
public interface DatabaseClient {
/**
* Prepare an SQL call returning a result.
* Specify a static {@code sql} string to execute. Contract for specifying a SQL call along with options leading to
* the exchange. The SQL string can contain either native parameter bind markers or named parameters (e.g.
* {@literal :foo, :bar}) when {@link NamedParameterExpander} is enabled.
*
* @see NamedParameterExpander
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
* @param sql must not be {@literal null} or empty.
* @return a new {@link GenericExecuteSpec}.
* @see NamedParameterExpander
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
*/
GenericExecuteSpec execute(String sql);
/**
* Specify a {@link Supplier SQL supplier} that provides SQL to execute. Contract for specifying a SQL call along with
* options leading to the exchange. The SQL string can contain either native parameter bind markers or named
* parameters (e.g. {@literal :foo, :bar}) when {@link NamedParameterExpander} is enabled.
* <p>
* Accepts {@link PreparedOperation} as SQL and binding {@link Supplier}.
* </p>
*
* @param sqlSupplier must not be {@literal null}.
* @return a new {@link GenericExecuteSpec}.
* @see NamedParameterExpander
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
* @see PreparedOperation
*/
GenericExecuteSpec execute(Supplier<String> sqlSupplier);
/**
* Prepare an SQL call returning a result.
*
* @deprecated will be removed with 1.0 M3. Use {@link #execute(String)} directly.
*/
@Deprecated
SqlSpec execute();
/**
@@ -157,7 +190,9 @@ public interface DatabaseClient {
*
* @see NamedParameterExpander
* @see DatabaseClient.Builder#namedParameters(NamedParameterExpander)
* @deprecated use {@code DatabaseClient.execute(…)} directly.
*/
@Deprecated
interface SqlSpec {
/**
@@ -166,6 +201,7 @@ public interface DatabaseClient {
* @param sql must not be {@literal null} or empty.
* @return a new {@link GenericExecuteSpec}.
*/
@Deprecated
GenericExecuteSpec sql(String sql);
/**
@@ -175,6 +211,7 @@ public interface DatabaseClient {
* @return a new {@link GenericExecuteSpec}.
* @see PreparedOperation
*/
@Deprecated
GenericExecuteSpec sql(Supplier<String> sqlSupplier);
}

View File

@@ -124,6 +124,22 @@ class DefaultDatabaseClient implements DatabaseClient, ConnectionAccessor {
return new DefaultDeleteFromSpec();
}
@Override
public GenericExecuteSpec execute(String sql) {
Assert.hasText(sql, "SQL must not be null or empty!");
return execute(() -> sql);
}
@Override
public GenericExecuteSpec execute(Supplier<String> sqlSupplier) {
Assert.notNull(sqlSupplier, "SQL Supplier must not be null!");
return createGenericExecuteSpec(sqlSupplier);
}
/**
* Execute a callback {@link Function} within a {@link Connection} scope. The function is responsible for creating a
* {@link Mono}. The connection is released after the {@link Mono} terminates (or the subscription is cancelled).

View File

@@ -41,7 +41,7 @@ import org.springframework.util.Assert;
* <pre class="code">
* Flux<Integer> transactionalFlux = databaseClient.inTransaction(db -> {
*
* return db.execute().sql("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
* return db.execute("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
* .bind("id", 1) //
* .bind("firstname", "Walter") //
* .bind("lastname", "White") //
@@ -56,7 +56,7 @@ import org.springframework.util.Assert;
* <pre class="code">
* Mono<Void> mono = databaseClient.beginTransaction()
* .then(databaseClient.execute()
* .sql("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
* .execute("INSERT INTO person (id, firstname, lastname) VALUES(:id, :firstname, :lastname)") //
* .bind("id", 1) //
* .bind("firstname", "Walter") //
* .bind("lastname", "White") //

View File

@@ -103,7 +103,7 @@ public abstract class AbstractR2dbcQuery implements RepositoryQuery {
BindableQuery query = createQuery(parameterAccessor);
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(parameterAccessor);
GenericExecuteSpec boundQuery = query.bind(databaseClient.execute().sql(query));
GenericExecuteSpec boundQuery = query.bind(databaseClient.execute(query));
FetchSpec<?> fetchSpec = boundQuery.as(resolveResultType(processor)).fetch();
String tableName = method.getEntityInformation().getTableName();

View File

@@ -117,7 +117,7 @@ public class SimpleR2dbcRepository<T, ID> implements ReactiveCrudRepository<T, I
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
return this.databaseClient.execute().sql(operation) //
return this.databaseClient.execute(operation) //
.as(this.entity.getJavaType()) //
.fetch() //
.one();
@@ -148,7 +148,7 @@ public class SimpleR2dbcRepository<T, ID> implements ReactiveCrudRepository<T, I
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
return this.databaseClient.execute().sql(operation) //
return this.databaseClient.execute(operation) //
.map((r, md) -> r) //
.first() //
.hasElement();
@@ -205,7 +205,7 @@ public class SimpleR2dbcRepository<T, ID> implements ReactiveCrudRepository<T, I
PreparedOperation<?> operation = mapper.getMappedObject(selectSpec);
return this.databaseClient.execute().sql(operation).as(this.entity.getJavaType()).fetch().all();
return this.databaseClient.execute(operation).as(this.entity.getJavaType()).fetch().all();
});
}
@@ -221,7 +221,7 @@ public class SimpleR2dbcRepository<T, ID> implements ReactiveCrudRepository<T, I
.from(table) //
.build();
return this.databaseClient.execute().sql(SqlRenderer.toString(select)) //
return this.databaseClient.execute(SqlRenderer.toString(select)) //
.map((r, md) -> r.get(0, Long.class)) //
.first() //
.defaultIfEmpty(0L);