#90 - Emit inserted object through SimpleR2dbcRepository.save(…) with given Id.

SimpleR2dbcRepository.save(…) now falls back to the saved object as emitted result if the INSERT statement does not return generated keys.

Adding H2 database engine for tests to simulate such behavior.

Original pull request: #90.
This commit is contained in:
Mark Paluch
2019-04-15 14:26:02 +02:00
committed by Jens Schauder
parent 30fb4d57b9
commit 652facb14a
4 changed files with 180 additions and 4 deletions

View File

@@ -75,7 +75,8 @@ public class SimpleR2dbcRepository<T, ID> implements ReactiveCrudRepository<T, I
.into(entity.getJavaType()) //
.using(objectToSave) //
.map(converter.populateIdIfNecessary(objectToSave)) //
.one();
.first() //
.defaultIfEmpty(objectToSave);
}
Object id = entity.getRequiredId(objectToSave);

View File

@@ -38,6 +38,7 @@ import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Persistable;
import org.springframework.data.r2dbc.function.DatabaseClient;
import org.springframework.data.r2dbc.function.ReactiveDataAccessStrategy;
import org.springframework.data.r2dbc.function.convert.MappingR2dbcConverter;
@@ -62,8 +63,8 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db
@Autowired private ReactiveDataAccessStrategy strategy;
private SimpleR2dbcRepository<LegoSet, Integer> repository;
private JdbcTemplate jdbc;
SimpleR2dbcRepository<LegoSet, Integer> repository;
JdbcTemplate jdbc;
@Before
public void before() {
@@ -372,9 +373,26 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db
@Table("legoset")
@AllArgsConstructor
@NoArgsConstructor
static class LegoSet {
static class LegoSet implements Persistable<Integer> {
@Id Integer id;
String name;
Integer manual;
@Override
public boolean isNew() {
return id == null;
}
}
static class AlwaysNewLegoSet extends LegoSet {
AlwaysNewLegoSet(Integer id, String name, Integer manual) {
super(id, name, manual);
}
@Override
public boolean isNew() {
return true;
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2019 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.repository.support;
import static org.assertj.core.api.Assertions.*;
import io.r2dbc.spi.ConnectionFactory;
import reactor.test.StepVerifier;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.testing.H2TestSupport;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Integration tests for {@link SimpleR2dbcRepository} against H2.
*
* @author Mark Paluch
*/
@RunWith(SpringRunner.class)
@ContextConfiguration
public class H2SimpleR2dbcRepositoryIntegrationTests extends AbstractSimpleR2dbcRepositoryIntegrationTests {
@Configuration
static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration {
@Override
public ConnectionFactory connectionFactory() {
return H2TestSupport.createConnectionFactory();
}
}
@Override
protected DataSource createDataSource() {
return H2TestSupport.createDataSource();
}
@Override
protected String getCreateTableStatement() {
return H2TestSupport.CREATE_TABLE_LEGOSET_WITH_ID_GENERATION;
}
@Test // gh-90
public void shouldInsertNewObjectWithGivenId() {
try {
this.jdbc.execute("DROP TABLE legoset");
} catch (DataAccessException e) {}
this.jdbc.execute(H2TestSupport.CREATE_TABLE_LEGOSET);
AlwaysNewLegoSet legoSet = new AlwaysNewLegoSet(9999, "SCHAUFELRADBAGGER", 12);
repository.save(legoSet) //
.as(StepVerifier::create) //
.consumeNextWith(actual -> {
assertThat(actual.getId()).isEqualTo(9999);
}).verifyComplete();
Map<String, Object> map = jdbc.queryForMap("SELECT * FROM legoset");
assertThat(map).containsEntry("name", "SCHAUFELRADBAGGER").containsEntry("manual", 12).containsKey("id");
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2019 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.testing;
import io.r2dbc.h2.H2ConnectionConfiguration;
import io.r2dbc.h2.H2ConnectionFactory;
import io.r2dbc.spi.ConnectionFactory;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
/**
* Utility class for testing against H2.
*
* @author Mark Paluch
*/
public class H2TestSupport {
public static String CREATE_TABLE_LEGOSET = "CREATE TABLE legoset (\n" //
+ " id integer CONSTRAINT id PRIMARY KEY,\n" //
+ " name varchar(255) NOT NULL,\n" //
+ " manual integer NULL\n" //
+ ");";
public static String CREATE_TABLE_LEGOSET_WITH_ID_GENERATION = "CREATE TABLE legoset (\n" //
+ " id serial CONSTRAINT id PRIMARY KEY,\n" //
+ " name varchar(255) NOT NULL,\n" //
+ " manual integer NULL\n" //
+ ");";
/**
* Creates a new {@link ConnectionFactory}.
*/
public static ConnectionFactory createConnectionFactory() {
return new H2ConnectionFactory(H2ConnectionConfiguration.builder() //
.inMemory("r2dbc") //
.username("sa") //
.password("") //
.option("DB_CLOSE_DELAY=-1").build());
}
/**
* Creates a new {@link DataSource}.
*/
public static DataSource createDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUsername("sa");
dataSource.setPassword("");
dataSource.setUrl("jdbc:h2:mem:r2dbc;DB_CLOSE_DELAY=-1");
return dataSource;
}
}