#440 - Create R2dbcEntityTemplate in R2dbcRepositoryFactoryBean.

We now create R2dbcEntityTemplate as part of R2dbcRepositoryFactoryBean initialization if the factory bean was configured with DatabaseClient and DataAccessStrategy only. Creating the template in the factory bean allows collecting entity callbacks for repository usage.
This commit is contained in:
Mark Paluch
2020-09-03 11:07:27 +02:00
parent dc8eb79797
commit b4002e5c3f
4 changed files with 48 additions and 3 deletions

View File

@@ -60,6 +60,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
private final ReactiveDataAccessStrategy dataAccessStrategy;
private final MappingContext<? extends RelationalPersistentEntity<?>, ? extends RelationalPersistentProperty> mappingContext;
private final R2dbcConverter converter;
private final R2dbcEntityOperations operations;
/**
* Creates a new {@link R2dbcRepositoryFactory} given {@link DatabaseClient} and {@link MappingContext}.
@@ -76,6 +77,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
this.dataAccessStrategy = dataAccessStrategy;
this.converter = dataAccessStrategy.getConverter();
this.mappingContext = this.converter.getMappingContext();
this.operations = new R2dbcEntityTemplate(this.databaseClient, this.dataAccessStrategy);
setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT);
}
@@ -93,6 +95,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
this.dataAccessStrategy = operations.getDataAccessStrategy();
this.converter = dataAccessStrategy.getConverter();
this.mappingContext = this.converter.getMappingContext();
this.operations = operations;
setEvaluationContextProvider(ReactiveQueryMethodEvaluationContextProvider.DEFAULT);
}
@@ -116,7 +119,7 @@ public class R2dbcRepositoryFactory extends ReactiveRepositoryFactorySupport {
information);
return getTargetRepositoryViaReflection(information, entityInformation,
new R2dbcEntityTemplate(this.databaseClient, this.dataAccessStrategy), this.converter);
operations, this.converter);
}
/*

View File

@@ -17,8 +17,12 @@ package org.springframework.data.r2dbc.repository.support;
import java.io.Serializable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.context.MappingContext;
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.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
@@ -38,11 +42,12 @@ import org.springframework.util.Assert;
* @see org.springframework.data.repository.reactive.ReactiveSortingRepository
*/
public class R2dbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
extends RepositoryFactoryBeanSupport<T, S, ID> {
extends RepositoryFactoryBeanSupport<T, S, ID> implements ApplicationContextAware {
private @Nullable DatabaseClient client;
private @Nullable ReactiveDataAccessStrategy dataAccessStrategy;
private @Nullable R2dbcEntityOperations operations;
private @Nullable ApplicationContext applicationContext;
private boolean mappingContextConfigured = false;
@@ -122,6 +127,15 @@ public class R2dbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
return new R2dbcRepositoryFactory(operations);
}
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
@@ -134,6 +148,14 @@ public class R2dbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
Assert.state(client != null, "DatabaseClient must not be null when R2dbcEntityOperations is not configured!");
Assert.state(dataAccessStrategy != null,
"ReactiveDataAccessStrategy must not be null when R2dbcEntityOperations is not configured!");
R2dbcEntityTemplate template = new R2dbcEntityTemplate(client, dataAccessStrategy);
if (applicationContext != null) {
template.setApplicationContext(applicationContext);
}
operations = template;
} else {
dataAccessStrategy = operations.getDataAccessStrategy();
}

View File

@@ -366,6 +366,7 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
static class Lego {
@Id Integer id;
}

View File

@@ -37,12 +37,14 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.annotation.Id;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.mapping.event.BeforeConvertCallback;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
import org.springframework.data.r2dbc.testing.ExternalDatabase;
import org.springframework.data.r2dbc.testing.PostgresTestSupport;
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,6 +72,23 @@ public class PostgresR2dbcRepositoryIntegrationTests extends AbstractR2dbcReposi
public ConnectionFactory connectionFactory() {
return PostgresTestSupport.createConnectionFactory(database);
}
@Bean
public BeforeConvertCallback<LegoSet> autogeneratedId(DatabaseClient client) {
return (entity, table) -> {
if (entity.getId() == null) {
return client.sql("SELECT nextval('person_seq');") //
.map(row -> row.get(0, Integer.class)) //
.first() //
.doOnNext(entity::setId) //
.thenReturn(entity);
}
return Mono.just(entity);
};
}
}
@Override
@@ -84,7 +103,7 @@ public class PostgresR2dbcRepositoryIntegrationTests extends AbstractR2dbcReposi
@Override
protected String getCreateTableStatement() {
return PostgresTestSupport.CREATE_TABLE_LEGOSET_WITH_ID_GENERATION;
return PostgresTestSupport.CREATE_TABLE_LEGOSET + ";CREATE SEQUENCE IF NOT EXISTS person_seq;";
}
@Override