diff --git a/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java b/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java index 9cba0478..32a70734 100644 --- a/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java +++ b/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java @@ -100,8 +100,15 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { additionalParameters.forEach(parameterSource::addValue); - operations.update(sql(domainType).getInsert(idValue == null, additionalParameters.keySet()), parameterSource, - holder); + boolean idValueDoesNotComeFromEntity = // + idValue == null // + || additionalParameters.containsKey(idProperty.getColumnName()); + + operations.update( // + sql(domainType).getInsert(idValueDoesNotComeFromEntity, additionalParameters.keySet()), // + parameterSource, // + holder // + ); setIdFromJdbc(instance, holder, persistentEntity); @@ -202,7 +209,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { MapSqlParameterSource parameter = new MapSqlParameterSource(property.getReverseColumnName(), rootId); - return (Iterable)operations.query(findAllByProperty, parameter, property.isQualified() // + return (Iterable) operations.query(findAllByProperty, parameter, property.isQualified() // ? getMapEntityRowMapper(property) // : getEntityRowMapper(actualType)); } diff --git a/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java new file mode 100644 index 00000000..687386b6 --- /dev/null +++ b/src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017 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 + * + * http://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.jdbc.core; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import lombok.RequiredArgsConstructor; + +import java.util.HashMap; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.data.annotation.Id; +import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; +import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; +import org.springframework.jdbc.support.KeyHolder; + +/** + * @author Jens Schauder + */ +public class DefaultDataAccessStrategyUnitTests { + + public static final long ID_FROM_ADDITIONAL_VALUES = 23L; + public static final long ORIGINAL_ID = 4711L; + + JdbcMappingContext context = new JdbcMappingContext(new DefaultNamingStrategy()); + NamedParameterJdbcOperations jdbcOperations = mock(NamedParameterJdbcOperations.class); + HashMap additionalParameters = new HashMap<>(); + ArgumentCaptor captor = ArgumentCaptor.forClass(SqlParameterSource.class); + + DefaultDataAccessStrategy accessStrategy = new DefaultDataAccessStrategy( // + new SqlGeneratorSource(context), // + jdbcOperations, // + context // + ); + + @Test // DATAJDBC-146 + public void additionalParameterForIdDoesNotLeadToDuplicateParameters() { + + additionalParameters.put("id", ID_FROM_ADDITIONAL_VALUES); + + accessStrategy.insert(new DummyEntity(ORIGINAL_ID), DummyEntity.class, additionalParameters); + + verify(jdbcOperations).update(eq("insert into DummyEntity (id) values (:id)"), captor.capture(), + any(KeyHolder.class)); + assertThat(captor.getValue().getValue("id")).isEqualTo(ID_FROM_ADDITIONAL_VALUES); + } + + @Test // DATAJDBC-146 + public void additionalParametersGetAddedToStatement() { + + additionalParameters.put("reference", ID_FROM_ADDITIONAL_VALUES); + + accessStrategy.insert(new DummyEntity(ORIGINAL_ID), DummyEntity.class, additionalParameters); + + verify(jdbcOperations).update(eq("insert into DummyEntity (id, reference) values (:id, :reference)"), + captor.capture(), any(KeyHolder.class)); + assertThat(captor.getValue().getValue("id")).isEqualTo(ORIGINAL_ID); + } + + @RequiredArgsConstructor + private static class DummyEntity { + + @Id private final Long id; + } + +}