From f43f054eff0c9b1f8158714e7522c3a0abd3ffd5 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 7 May 2019 14:43:41 +0200 Subject: [PATCH] DATAJDBC-359 - Polishing. Deprecate remaining DataAccessStrategy types in jdbc.core and create replacements in jdbc.core.convert. Migrate using code to replacement types. Simplify warnings and if flows. Add since version to deprecations. Move MyBatisDataAccessStrategyUnitTests from core to mybatis package. Original pull request: #150. --- .../core/CascadingDataAccessStrategy.java | 148 +-------------- .../data/jdbc/core/DataAccessStrategy.java | 143 +------------- .../jdbc/core/DefaultDataAccessStrategy.java | 31 ++-- .../jdbc/core/DefaultJdbcInterpreter.java | 1 + .../core/DelegatingDataAccessStrategy.java | 152 +-------------- .../data/jdbc/core/EntityRowMapper.java | 7 +- .../data/jdbc/core/JdbcAggregateTemplate.java | 1 + .../jdbc/core/convert/BasicJdbcConverter.java | 22 +-- .../convert/CascadingDataAccessStrategy.java | 174 ++++++++++++++++++ .../jdbc/core/convert/DataAccessStrategy.java | 164 +++++++++++++++++ .../convert/DefaultDataAccessStrategy.java | 2 +- .../convert/DelegatingDataAccessStrategy.java | 171 +++++++++++++++++ .../jdbc/core/convert/EntityRowMapper.java | 3 +- .../core/{ => convert}/FunctionCollector.java | 14 +- .../data/jdbc/core/convert/JdbcConverter.java | 5 +- .../data/jdbc/core/convert/SqlGenerator.java | 15 +- .../mybatis/MyBatisDataAccessStrategy.java | 10 +- .../config/AbstractJdbcConfiguration.java | 2 +- .../repository/config/JdbcConfiguration.java | 4 +- .../support/JdbcQueryLookupStrategy.java | 2 +- .../support/JdbcRepositoryFactory.java | 2 +- .../support/JdbcRepositoryFactoryBean.java | 4 +- .../core/DefaultJdbcInterpreterUnitTests.java | 1 + ...AggregateTemplateHsqlIntegrationTests.java | 1 + ...JdbcAggregateTemplateIntegrationTests.java | 1 + .../CascadingDataAccessStrategyUnitTests.java | 7 +- .../convert/EntityRowMapperUnitTests.java | 1 - .../MyBatisDataAccessStrategyUnitTests.java | 13 +- .../mybatis/MyBatisHsqlIntegrationTests.java | 3 +- ...nableJdbcRepositoriesIntegrationTests.java | 2 +- .../JdbcQueryLookupStrategyUnitTests.java | 11 +- .../JdbcRepositoryFactoryBeanUnitTests.java | 3 +- .../data/jdbc/testing/TestConfiguration.java | 3 +- .../core/conversion/AggregateChange.java | 39 ++-- 34 files changed, 634 insertions(+), 528 deletions(-) create mode 100644 spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategy.java create mode 100644 spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java create mode 100644 spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DelegatingDataAccessStrategy.java rename spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/{ => convert}/FunctionCollector.java (96%) rename spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/{ => convert}/CascadingDataAccessStrategyUnitTests.java (93%) rename spring-data-jdbc/src/test/java/org/springframework/data/jdbc/{core => mybatis}/MyBatisDataAccessStrategyUnitTests.java (94%) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java index 35ae254a..f09e9808 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategy.java @@ -15,158 +15,24 @@ */ package org.springframework.data.jdbc.core; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import org.springframework.data.relational.domain.Identifier; -import org.springframework.data.mapping.PersistentPropertyPath; -import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; /** * Delegates each methods to the {@link DataAccessStrategy}s passed to the constructor in turn until the first that does * not throw an exception. * * @author Jens Schauder + * @author Mark Paluch + * @deprecated since 1.1, use {@link org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy} */ -public class CascadingDataAccessStrategy implements DataAccessStrategy { - - private final List strategies; +@Deprecated +public class CascadingDataAccessStrategy + extends org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy { public CascadingDataAccessStrategy(List strategies) { - this.strategies = new ArrayList<>(strategies); + super(strategies); } - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map) - */ - @Override - public Object insert(T instance, Class domainType, Map additionalParameters) { - return collect(das -> das.insert(instance, domainType, additionalParameters)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys) - */ - @Override - public Object insert(T instance, Class domainType, Identifier identifier) { - return collect(das -> das.insert(instance, domainType, identifier)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class) - */ - @Override - public boolean update(S instance, Class domainType) { - return collect(das -> das.update(instance, domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class) - */ - @Override - public void delete(Object id, Class domainType) { - collectVoid(das -> das.delete(id, domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PersistentPropertyPath) - */ - @Override - public void delete(Object rootId, PersistentPropertyPath propertyPath) { - collectVoid(das -> das.delete(rootId, propertyPath)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class) - */ - @Override - public void deleteAll(Class domainType) { - collectVoid(das -> das.deleteAll(domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath) - */ - @Override - public void deleteAll(PersistentPropertyPath propertyPath) { - collectVoid(das -> das.deleteAll(propertyPath)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class) - */ - @Override - public long count(Class domainType) { - return collect(das -> das.count(domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class) - */ - @Override - public T findById(Object id, Class domainType) { - return collect(das -> das.findById(id, domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class) - */ - @Override - public Iterable findAll(Class domainType) { - return collect(das -> das.findAll(domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class) - */ - @Override - public Iterable findAllById(Iterable ids, Class domainType) { - return collect(das -> das.findAllById(ids, domainType)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.relational.core.mapping.RelationalPersistentProperty) - */ - @Override - public Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property) { - return collect(das -> das.findAllByProperty(rootId, property)); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class) - */ - @Override - public boolean existsById(Object id, Class domainType) { - return collect(das -> das.existsById(id, domainType)); - } - - private T collect(Function function) { - - // Keep as Eclipse fails to compile if <> is used. - return strategies.stream().collect(new FunctionCollector<>(function)); - } - - private void collectVoid(Consumer consumer) { - - collect(das -> { - consumer.accept(das); - return null; - }); - } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java index 1c0bac8b..08442218 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DataAccessStrategy.java @@ -15,149 +15,14 @@ */ package org.springframework.data.jdbc.core; -import java.util.Map; - -import org.springframework.data.mapping.PersistentPropertyPath; -import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; -import org.springframework.data.relational.domain.Identifier; -import org.springframework.lang.Nullable; - /** * Abstraction for accesses to the database that should be implementable with a single SQL statement per method and * relates to a single entity as opposed to {@link JdbcAggregateOperations} which provides interactions related to * complete aggregates. * * @author Jens Schauder + * @author Mark Paluch + * @deprecated since 1.1, use {@link org.springframework.data.jdbc.core.convert.DataAccessStrategy} */ -public interface DataAccessStrategy { - - /** - * Inserts a the data of a single entity. Referenced entities don't get handled. - * - * @param instance the instance to be stored. Must not be {@code null}. - * @param domainType the type of the instance. Must not be {@code null}. - * @param additionalParameters name-value pairs of additional parameters. Especially ids of parent entities that need - * to get referenced are contained in this map. Must not be {@code null}. - * @param the type of the instance. - * @return the id generated by the database if any. - * @deprecated since 1.1, use {@link #insert(Object, Class, Identifier)} instead. - */ - @Deprecated - Object insert(T instance, Class domainType, Map additionalParameters); - - /** - * Inserts a the data of a single entity. Referenced entities don't get handled. - * - * @param instance the instance to be stored. Must not be {@code null}. - * @param domainType the type of the instance. Must not be {@code null}. - * @param identifier information about data that needs to be considered for the insert but which is not part of the - * entity. Namely references back to a parent entity and key/index columns for entities that are stored in a - * {@link Map} or {@link java.util.List}. - * @param the type of the instance. - * @return the id generated by the database if any. - * @since 1.1 - */ - default Object insert(T instance, Class domainType, Identifier identifier){ - return insert(instance, domainType, identifier.toMap()); - } - - /** - * Updates the data of a single entity in the database. Referenced entities don't get handled. - * - * @param instance the instance to save. Must not be {@code null}. - * @param domainType the type of the instance to save. Must not be {@code null}. - * @param the type of the instance to save. - * @return whether the update actually updated a row. - */ - boolean update(T instance, Class domainType); - - /** - * deletes a single row identified by the id, from the table identified by the domainType. Does not handle cascading - * deletes. - * - * @param id the id of the row to be deleted. Must not be {@code null}. - * @param domainType the type of entity to be deleted. Implicitly determines the table to operate on. Must not be - * {@code null}. - */ - void delete(Object id, Class domainType); - - /** - * Deletes all entities reachable via {@literal propertyPath} from the instance identified by {@literal rootId}. - * - * @param rootId Id of the root object on which the {@literal propertyPath} is based. Must not be {@code null}. - * @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}. - */ - void delete(Object rootId, PersistentPropertyPath propertyPath); - - /** - * Deletes all entities of the given domain type. - * - * @param domainType the domain type for which to delete all entries. Must not be {@code null}. - * @param type of the domain type. - */ - void deleteAll(Class domainType); - - /** - * Deletes all entities reachable via {@literal propertyPath} from any instance. - * - * @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}. - */ - void deleteAll(PersistentPropertyPath propertyPath); - - /** - * Counts the rows in the table representing the given domain type. - * - * @param domainType the domain type for which to count the elements. Must not be {@code null}. - * @return the count. Guaranteed to be not {@code null}. - */ - long count(Class domainType); - - /** - * Loads a single entity identified by type and id. - * - * @param id the id of the entity to load. Must not be {@code null}. - * @param domainType the domain type of the entity. Must not be {@code null}. - * @param the type of the entity. - * @return Might return {@code null}. - */ - @Nullable - T findById(Object id, Class domainType); - - /** - * Loads all entities of the given type. - * - * @param domainType the type of entities to load. Must not be {@code null}. - * @param the type of entities to load. - * @return Guaranteed to be not {@code null}. - */ - Iterable findAll(Class domainType); - - /** - * Loads all entities that match one of the ids passed as an argument. It is not guaranteed that the number of ids - * passed in matches the number of entities returned. - * - * @param ids the Ids of the entities to load. Must not be {@code null}. - * @param domainType the type of entities to laod. Must not be {@code null}. - * @param type of entities to load. - * @return the loaded entities. Guaranteed to be not {@code null}. - */ - Iterable findAllById(Iterable ids, Class domainType); - - /** - * Finds all entities reachable via {@literal property} from the instance identified by {@literal rootId}. - * - * @param rootId Id of the root object on which the {@literal propertyPath} is based. - * @param property Leading from the root object to the entities to be found. - */ - Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property); - - /** - * returns if a row with the given id exists for the given type. - * - * @param id the id of the entity for which to check. Must not be {@code null}. - * @param domainType the type of the entity to check for. Must not be {@code null}. - * @param the type of the entity. - * @return {@code true} if a matching row exists, otherwise {@code false}. - */ - boolean existsById(Object id, Class domainType); -} +@Deprecated +public interface DataAccessStrategy extends org.springframework.data.jdbc.core.convert.DataAccessStrategy {} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java index 5154c3f8..02ec95b0 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2017-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. @@ -15,6 +15,7 @@ */ package org.springframework.data.jdbc.core; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.SqlGeneratorSource; import org.springframework.data.relational.core.mapping.RelationalMappingContext; @@ -22,25 +23,25 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; /** * The default {@link DataAccessStrategy} is to generate SQL statements based on meta data from the entity. - * + * * @author Jens Schauder - * @deprecated Use {@link org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy} instead. + * @deprecated since 1.1, use {@link org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy} instead. */ @Deprecated public class DefaultDataAccessStrategy extends org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy { /** - * Creates a {@link org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy} which references it self for resolution of recursive data accesses. - * Only suitable if this is the only access strategy in use. - * - * @param sqlGeneratorSource must not be {@literal null}. - * @param context must not be {@literal null}. - * @param converter must not be {@literal null}. - * @param operations must not be {@literal null}. - */ - public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, RelationalMappingContext context, - JdbcConverter converter, NamedParameterJdbcOperations operations) { - super(sqlGeneratorSource, context, converter, operations); - } + * Creates a {@link org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy} which references it self for + * resolution of recursive data accesses. Only suitable if this is the only access strategy in use. + * + * @param sqlGeneratorSource must not be {@literal null}. + * @param context must not be {@literal null}. + * @param converter must not be {@literal null}. + * @param operations must not be {@literal null}. + */ + public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, RelationalMappingContext context, + JdbcConverter converter, NamedParameterJdbcOperations operations) { + super(sqlGeneratorSource, context, converter, operations); + } } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java index 23293994..7dd07903 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java @@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor; import java.util.Collections; import java.util.Map; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.relational.core.conversion.DbAction; import org.springframework.data.relational.core.conversion.DbAction.Delete; diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java index ec327a9b..ac6299c7 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DelegatingDataAccessStrategy.java @@ -15,156 +15,16 @@ */ package org.springframework.data.jdbc.core; -import java.util.Map; - -import org.springframework.data.relational.domain.Identifier; -import org.springframework.data.mapping.PersistentPropertyPath; -import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; -import org.springframework.util.Assert; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; /** * Delegates all method calls to an instance set after construction. This is useful for {@link DataAccessStrategy}s with * cyclic dependencies. * * @author Jens Schauder + * @author Mark Paluch + * @deprecated since 1.1, use {@link org.springframework.data.jdbc.core.convert.DelegatingDataAccessStrategy}. */ -public class DelegatingDataAccessStrategy implements DataAccessStrategy { - - private DataAccessStrategy delegate; - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map) - */ - @Override - public Object insert(T instance, Class domainType, Map additionalParameters) { - return delegate.insert(instance, domainType, additionalParameters); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys) - */ - @Override - public Object insert(T instance, Class domainType, Identifier identifier) { - return delegate.insert(instance, domainType, identifier); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class) - */ - @Override - public boolean update(S instance, Class domainType) { - return delegate.update(instance, domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PersistentPropertyPath) - */ - @Override - public void delete(Object rootId, PersistentPropertyPath propertyPath) { - delegate.delete(rootId, propertyPath); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class) - */ - @Override - public void delete(Object id, Class domainType) { - delegate.delete(id, domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class) - */ - @Override - public void deleteAll(Class domainType) { - delegate.deleteAll(domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath) - */ - @Override - public void deleteAll(PersistentPropertyPath propertyPath) { - delegate.deleteAll(propertyPath); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class) - */ - @Override - public long count(Class domainType) { - return delegate.count(domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class) - */ - @Override - public T findById(Object id, Class domainType) { - - Assert.notNull(delegate, "Delegate is null"); - - return delegate.findById(id, domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class) - */ - @Override - public Iterable findAll(Class domainType) { - return delegate.findAll(domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class) - */ - @Override - public Iterable findAllById(Iterable ids, Class domainType) { - return delegate.findAllById(ids, domainType); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.relational.core.mapping.RelationalPersistentProperty) - */ - @Override - public Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property) { - - Assert.notNull(delegate, "Delegate is null"); - - return delegate.findAllByProperty(rootId, property); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class) - */ - @Override - public boolean existsById(Object id, Class domainType) { - return delegate.existsById(id, domainType); - } - - /** - * Must be called exactly once before calling any of the other methods. - * - * @param delegate Must not be {@literal null} - */ - public void setDelegate(DataAccessStrategy delegate) { - - Assert.isNull(this.delegate, "The delegate must be set exactly once"); - Assert.notNull(delegate, "The delegate must not be set to null"); - - this.delegate = delegate; - } -} +@Deprecated +public class DelegatingDataAccessStrategy + extends org.springframework.data.jdbc.core.convert.DelegatingDataAccessStrategy {} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java index 1080486b..9d0c3e46 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2017-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. @@ -15,13 +15,13 @@ */ package org.springframework.data.jdbc.core; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; /** * @author Jens Schauder - * - * @deprecated Use {@link org.springframework.data.jdbc.core.convert.EntityRowMapper} instead. + * @deprecated since 1.1, use {@link org.springframework.data.jdbc.core.convert.EntityRowMapper} instead. */ @Deprecated public class EntityRowMapper extends org.springframework.data.jdbc.core.convert.EntityRowMapper { @@ -30,5 +30,4 @@ public class EntityRowMapper extends org.springframework.data.jdbc.core.conve DataAccessStrategy accessStrategy) { super(entity, converter, accessStrategy); } - } diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java index d0be790c..c4b9b3bf 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java @@ -18,6 +18,7 @@ package org.springframework.data.jdbc.core; import java.util.Optional; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.mapping.IdentifierAccessor; import org.springframework.data.relational.core.conversion.AggregateChange; import org.springframework.data.relational.core.conversion.AggregateChange.Kind; diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java index 42cdebf2..7b9a48f3 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BasicJdbcConverter.java @@ -15,8 +15,6 @@ */ package org.springframework.data.jdbc.core.convert; -import lombok.Value; - import java.sql.Array; import java.sql.JDBCType; import java.sql.ResultSet; @@ -29,7 +27,6 @@ import org.slf4j.LoggerFactory; import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.CustomConversions; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.mapping.AggregateReference; import org.springframework.data.jdbc.support.JdbcUtil; import org.springframework.data.mapping.MappingException; @@ -258,7 +255,6 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc return new ReadingContext(entity, accessStrategy, resultSet).mapRow(); } - @Value private class ReadingContext { private final RelationalPersistentEntity entity; @@ -274,10 +270,12 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc this.idProperty = entity.getIdProperty(); this.accessStrategy = accessStrategy; this.resultSet = resultSet; - this.path = new PersistentPropertyPathExtension((MappingContext, RelationalPersistentProperty>) getMappingContext(), entity); + this.path = new PersistentPropertyPathExtension( + (MappingContext, RelationalPersistentProperty>) getMappingContext(), entity); } - public ReadingContext(RelationalPersistentEntity entity, DataAccessStrategy accessStrategy, ResultSet resultSet, PersistentPropertyPathExtension path) { + public ReadingContext(RelationalPersistentEntity entity, DataAccessStrategy accessStrategy, ResultSet resultSet, + PersistentPropertyPathExtension path) { this.entity = entity; this.idProperty = entity.getIdProperty(); @@ -286,8 +284,8 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc this.path = path; } - private ReadingContext extendBy(RelationalPersistentProperty property) { - return new ReadingContext(entity, accessStrategy, resultSet, path.extendBy(property)); + private ReadingContext extendBy(RelationalPersistentProperty property) { + return new ReadingContext<>(entity, accessStrategy, resultSet, path.extendBy(property)); } T mapRow() { @@ -359,6 +357,7 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc } + @SuppressWarnings("unchecked") private Object readEmbeddedEntityFrom(@Nullable Object id, RelationalPersistentProperty property) { ReadingContext newContext = extendBy(property); @@ -367,7 +366,6 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc Object instance = newContext.createInstanceInternal(entity, null); - @SuppressWarnings("unchecked") PersistentPropertyAccessor accessor = getPropertyAccessor((PersistentEntity) entity, instance); for (RelationalPersistentProperty p : entity) { @@ -380,10 +378,8 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc @Nullable private S readEntityFrom(RelationalPersistentProperty property, PersistentPropertyPathExtension path) { - @SuppressWarnings("unchecked") - ReadingContext newContext = extendBy(property); + ReadingContext newContext = extendBy(property); - @SuppressWarnings("unchecked") RelationalPersistentEntity entity = (RelationalPersistentEntity) getMappingContext() .getRequiredPersistentEntity(property.getActualType()); @@ -425,7 +421,7 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc private S createInstanceInternal(RelationalPersistentEntity entity, @Nullable Object idValue) { - return createInstance(entity,parameter -> { + return createInstance(entity, parameter -> { String parameterName = parameter.getName(); diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategy.java new file mode 100644 index 00000000..448377aa --- /dev/null +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategy.java @@ -0,0 +1,174 @@ +/* + * Copyright 2017-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.jdbc.core.convert; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.data.relational.domain.Identifier; + +/** + * Delegates each methods to the {@link DataAccessStrategy}s passed to the constructor in turn until the first that does + * not throw an exception. + * + * @author Jens Schauder + * @author Mark Paluch + * @since 1.1 + */ +public class CascadingDataAccessStrategy implements DataAccessStrategy { + + private final List strategies; + + public CascadingDataAccessStrategy(List strategies) { + this.strategies = new ArrayList<>(strategies); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map) + */ + @Override + public Object insert(T instance, Class domainType, Map additionalParameters) { + return collect(das -> das.insert(instance, domainType, additionalParameters)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys) + */ + @Override + public Object insert(T instance, Class domainType, Identifier identifier) { + return collect(das -> das.insert(instance, domainType, identifier)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class) + */ + @Override + public boolean update(S instance, Class domainType) { + return collect(das -> das.update(instance, domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class) + */ + @Override + public void delete(Object id, Class domainType) { + collectVoid(das -> das.delete(id, domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PersistentPropertyPath) + */ + @Override + public void delete(Object rootId, PersistentPropertyPath propertyPath) { + collectVoid(das -> das.delete(rootId, propertyPath)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class) + */ + @Override + public void deleteAll(Class domainType) { + collectVoid(das -> das.deleteAll(domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath) + */ + @Override + public void deleteAll(PersistentPropertyPath propertyPath) { + collectVoid(das -> das.deleteAll(propertyPath)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class) + */ + @Override + public long count(Class domainType) { + return collect(das -> das.count(domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class) + */ + @Override + public T findById(Object id, Class domainType) { + return collect(das -> das.findById(id, domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class) + */ + @Override + public Iterable findAll(Class domainType) { + return collect(das -> das.findAll(domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class) + */ + @Override + public Iterable findAllById(Iterable ids, Class domainType) { + return collect(das -> das.findAllById(ids, domainType)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.relational.core.mapping.RelationalPersistentProperty) + */ + @Override + public Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property) { + return collect(das -> das.findAllByProperty(rootId, property)); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class) + */ + @Override + public boolean existsById(Object id, Class domainType) { + return collect(das -> das.existsById(id, domainType)); + } + + private T collect(Function function) { + + // Keep as Eclipse fails to compile if <> is used. + return strategies.stream().collect(new FunctionCollector<>(function)); + } + + private void collectVoid(Consumer consumer) { + + collect(das -> { + consumer.accept(das); + return null; + }); + } +} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java new file mode 100644 index 00000000..b42b7de2 --- /dev/null +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DataAccessStrategy.java @@ -0,0 +1,164 @@ +/* + * 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.jdbc.core.convert; + +import java.util.Map; + +import org.springframework.data.jdbc.core.JdbcAggregateOperations; +import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.data.relational.domain.Identifier; +import org.springframework.lang.Nullable; + +/** + * Abstraction for accesses to the database that should be implementable with a single SQL statement per method and + * relates to a single entity as opposed to {@link JdbcAggregateOperations} which provides interactions related to + * complete aggregates. + * + * @author Jens Schauder + */ +public interface DataAccessStrategy { + + /** + * Inserts a the data of a single entity. Referenced entities don't get handled. + * + * @param instance the instance to be stored. Must not be {@code null}. + * @param domainType the type of the instance. Must not be {@code null}. + * @param additionalParameters name-value pairs of additional parameters. Especially ids of parent entities that need + * to get referenced are contained in this map. Must not be {@code null}. + * @param the type of the instance. + * @return the id generated by the database if any. + * @deprecated since 1.1, use {@link #insert(Object, Class, Identifier)} instead. + */ + @Deprecated + Object insert(T instance, Class domainType, Map additionalParameters); + + /** + * Inserts a the data of a single entity. Referenced entities don't get handled. + * + * @param instance the instance to be stored. Must not be {@code null}. + * @param domainType the type of the instance. Must not be {@code null}. + * @param identifier information about data that needs to be considered for the insert but which is not part of the + * entity. Namely references back to a parent entity and key/index columns for entities that are stored in a + * {@link Map} or {@link java.util.List}. + * @param the type of the instance. + * @return the id generated by the database if any. + * @since 1.1 + */ + default Object insert(T instance, Class domainType, Identifier identifier) { + return insert(instance, domainType, identifier.toMap()); + } + + /** + * Updates the data of a single entity in the database. Referenced entities don't get handled. + * + * @param instance the instance to save. Must not be {@code null}. + * @param domainType the type of the instance to save. Must not be {@code null}. + * @param the type of the instance to save. + * @return whether the update actually updated a row. + */ + boolean update(T instance, Class domainType); + + /** + * deletes a single row identified by the id, from the table identified by the domainType. Does not handle cascading + * deletes. + * + * @param id the id of the row to be deleted. Must not be {@code null}. + * @param domainType the type of entity to be deleted. Implicitly determines the table to operate on. Must not be + * {@code null}. + */ + void delete(Object id, Class domainType); + + /** + * Deletes all entities reachable via {@literal propertyPath} from the instance identified by {@literal rootId}. + * + * @param rootId Id of the root object on which the {@literal propertyPath} is based. Must not be {@code null}. + * @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}. + */ + void delete(Object rootId, PersistentPropertyPath propertyPath); + + /** + * Deletes all entities of the given domain type. + * + * @param domainType the domain type for which to delete all entries. Must not be {@code null}. + * @param type of the domain type. + */ + void deleteAll(Class domainType); + + /** + * Deletes all entities reachable via {@literal propertyPath} from any instance. + * + * @param propertyPath Leading from the root object to the entities to be deleted. Must not be {@code null}. + */ + void deleteAll(PersistentPropertyPath propertyPath); + + /** + * Counts the rows in the table representing the given domain type. + * + * @param domainType the domain type for which to count the elements. Must not be {@code null}. + * @return the count. Guaranteed to be not {@code null}. + */ + long count(Class domainType); + + /** + * Loads a single entity identified by type and id. + * + * @param id the id of the entity to load. Must not be {@code null}. + * @param domainType the domain type of the entity. Must not be {@code null}. + * @param the type of the entity. + * @return Might return {@code null}. + */ + @Nullable + T findById(Object id, Class domainType); + + /** + * Loads all entities of the given type. + * + * @param domainType the type of entities to load. Must not be {@code null}. + * @param the type of entities to load. + * @return Guaranteed to be not {@code null}. + */ + Iterable findAll(Class domainType); + + /** + * Loads all entities that match one of the ids passed as an argument. It is not guaranteed that the number of ids + * passed in matches the number of entities returned. + * + * @param ids the Ids of the entities to load. Must not be {@code null}. + * @param domainType the type of entities to laod. Must not be {@code null}. + * @param type of entities to load. + * @return the loaded entities. Guaranteed to be not {@code null}. + */ + Iterable findAllById(Iterable ids, Class domainType); + + /** + * Finds all entities reachable via {@literal property} from the instance identified by {@literal rootId}. + * + * @param rootId Id of the root object on which the {@literal propertyPath} is based. + * @param property Leading from the root object to the entities to be found. + */ + Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property); + + /** + * returns if a row with the given id exists for the given type. + * + * @param id the id of the entity for which to check. Must not be {@code null}. + * @param domainType the type of the entity to check for. Must not be {@code null}. + * @param the type of the entity. + * @return {@code true} if a matching row exists, otherwise {@code false}. + */ + boolean existsById(Object id, Class domainType); +} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java index e6f8e7d0..685f5f80 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DefaultDataAccessStrategy.java @@ -29,7 +29,6 @@ import java.util.function.Predicate; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.support.JdbcUtil; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; @@ -55,6 +54,7 @@ import org.springframework.util.Assert; * @author Mark Paluch * @author Thomas Lang * @author Bastian Wilhelm + * @since 1.1 */ public class DefaultDataAccessStrategy implements DataAccessStrategy { diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DelegatingDataAccessStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DelegatingDataAccessStrategy.java new file mode 100644 index 00000000..83022c0e --- /dev/null +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/DelegatingDataAccessStrategy.java @@ -0,0 +1,171 @@ +/* + * Copyright 2017-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.jdbc.core.convert; + +import java.util.Map; + +import org.springframework.data.mapping.PersistentPropertyPath; +import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; +import org.springframework.data.relational.domain.Identifier; +import org.springframework.util.Assert; + +/** + * Delegates all method calls to an instance set after construction. This is useful for {@link DataAccessStrategy}s with + * cyclic dependencies. + * + * @author Jens Schauder + * @since 1.1 + */ +public class DelegatingDataAccessStrategy implements DataAccessStrategy { + + private DataAccessStrategy delegate; + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map) + */ + @Override + public Object insert(T instance, Class domainType, Map additionalParameters) { + return delegate.insert(instance, domainType, additionalParameters); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys) + */ + @Override + public Object insert(T instance, Class domainType, Identifier identifier) { + return delegate.insert(instance, domainType, identifier); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class) + */ + @Override + public boolean update(S instance, Class domainType) { + return delegate.update(instance, domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PersistentPropertyPath) + */ + @Override + public void delete(Object rootId, PersistentPropertyPath propertyPath) { + delegate.delete(rootId, propertyPath); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class) + */ + @Override + public void delete(Object id, Class domainType) { + delegate.delete(id, domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class) + */ + @Override + public void deleteAll(Class domainType) { + delegate.deleteAll(domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath) + */ + @Override + public void deleteAll(PersistentPropertyPath propertyPath) { + delegate.deleteAll(propertyPath); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class) + */ + @Override + public long count(Class domainType) { + return delegate.count(domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class) + */ + @Override + public T findById(Object id, Class domainType) { + + Assert.notNull(delegate, "Delegate is null"); + + return delegate.findById(id, domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class) + */ + @Override + public Iterable findAll(Class domainType) { + return delegate.findAll(domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class) + */ + @Override + public Iterable findAllById(Iterable ids, Class domainType) { + return delegate.findAllById(ids, domainType); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.relational.core.mapping.RelationalPersistentProperty) + */ + @Override + public Iterable findAllByProperty(Object rootId, RelationalPersistentProperty property) { + + Assert.notNull(delegate, "Delegate is null"); + + return delegate.findAllByProperty(rootId, property); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class) + */ + @Override + public boolean existsById(Object id, Class domainType) { + return delegate.existsById(id, domainType); + } + + /** + * Must be called exactly once before calling any of the other methods. + * + * @param delegate Must not be {@literal null} + */ + public void setDelegate(DataAccessStrategy delegate) { + + Assert.isNull(this.delegate, "The delegate must be set exactly once"); + Assert.notNull(delegate, "The delegate must not be set to null"); + + this.delegate = delegate; + } +} diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/EntityRowMapper.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/EntityRowMapper.java index 03e9fd4d..fa5266ae 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/EntityRowMapper.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/EntityRowMapper.java @@ -17,8 +17,6 @@ package org.springframework.data.jdbc.core.convert; import java.sql.ResultSet; -import org.springframework.data.jdbc.core.DataAccessStrategy; -import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; import org.springframework.jdbc.core.RowMapper; @@ -31,6 +29,7 @@ import org.springframework.jdbc.core.RowMapper; * @author Mark Paluch * @author Maciej Walkowiak * @author Bastian Wilhelm + * @since 1.1 */ public class EntityRowMapper implements RowMapper { diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/FunctionCollector.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/FunctionCollector.java similarity index 96% rename from spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/FunctionCollector.java rename to spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/FunctionCollector.java index c55bc46b..2ae9ebbe 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/FunctionCollector.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/FunctionCollector.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jdbc.core; +package org.springframework.data.jdbc.core.convert; import java.util.Collections; import java.util.LinkedList; @@ -43,7 +43,7 @@ class FunctionCollector implements Collector implements Collector implements Collector implements Collector implements Collector * Use a {@link SqlSessionTemplate} for {@link SqlSession} or a similar implementation tying the session to the proper * transaction. Note that the resulting {@link DataAccessStrategy} only handles MyBatis. It does not include the - * functionality of the {@link DefaultDataAccessStrategy} which one normally still - * wants. Use + * functionality of the {@link DefaultDataAccessStrategy} which one normally still wants. Use * {@link #createCombinedAccessStrategy(RelationalMappingContext, JdbcConverter, NamedParameterJdbcOperations, SqlSession, NamespaceStrategy)} * to create such a {@link DataAccessStrategy}. * diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java index bdd10ee5..d91bd714 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java @@ -21,9 +21,9 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.JdbcAggregateTemplate; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; import org.springframework.data.jdbc.core.convert.JdbcConverter; diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java index 6835aee5..a25512df 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java @@ -21,10 +21,10 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.JdbcAggregateOperations; import org.springframework.data.jdbc.core.JdbcAggregateTemplate; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.JdbcCustomConversions; @@ -94,7 +94,7 @@ public class JdbcConfiguration { /** * Register a {@link JdbcAggregateTemplate} as a bean for easy use in applications that need a lower level of * abstraction than the normal repository abstraction. - * + * * @param publisher * @param context * @param converter diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java index d604c03f..8d0ccf62 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java @@ -18,7 +18,7 @@ package org.springframework.data.jdbc.repository.support; import java.lang.reflect.Method; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.jdbc.core.DataAccessStrategy; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.EntityRowMapper; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.repository.QueryMappingConfiguration; diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java index 65601b0b..ba301d4e 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java @@ -18,8 +18,8 @@ package org.springframework.data.jdbc.repository.support; import java.util.Optional; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.JdbcAggregateTemplate; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.repository.QueryMappingConfiguration; import org.springframework.data.jdbc.repository.RowMapperMap; diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java index 0860fbe7..2948d680 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java @@ -21,7 +21,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; -import org.springframework.data.jdbc.core.DataAccessStrategy; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.SqlGeneratorSource; @@ -44,7 +44,7 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Mark Paluch */ -public class JdbcRepositoryFactoryBean, S, ID extends Serializable> // +public class JdbcRepositoryFactoryBean, S, ID extends Serializable> extends TransactionalRepositoryFactoryBeanSupport implements ApplicationEventPublisherAware { private ApplicationEventPublisher publisher; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java index 20748a8f..27a6d05b 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.*; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.data.annotation.Id; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.relational.core.conversion.DbAction.Insert; import org.springframework.data.relational.core.conversion.DbAction.InsertRoot; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/ImmutableAggregateTemplateHsqlIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/ImmutableAggregateTemplateHsqlIntegrationTests.java index 481e7d1f..3095a7ec 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/ImmutableAggregateTemplateHsqlIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/ImmutableAggregateTemplateHsqlIntegrationTests.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.data.relational.core.conversion.RelationalConverter; import org.springframework.data.relational.core.mapping.RelationalMappingContext; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java index 7747c2fa..f2f910fa 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateIntegrationTests.java @@ -37,6 +37,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.annotation.Id; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.testing.DatabaseProfileValueSource; import org.springframework.data.jdbc.testing.TestConfiguration; import org.springframework.data.relational.core.conversion.RelationalConverter; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategyUnitTests.java similarity index 93% rename from spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategyUnitTests.java rename to spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategyUnitTests.java index de374ea7..c74a1113 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/CascadingDataAccessStrategyUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/CascadingDataAccessStrategyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jdbc.core; +package org.springframework.data.jdbc.core.convert; import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; @@ -24,7 +24,8 @@ import junit.framework.AssertionFailedError; import java.util.Collections; import org.junit.Test; -import org.springframework.data.jdbc.core.FunctionCollector.CombinedDataAccessException; + +import org.springframework.data.jdbc.core.convert.FunctionCollector.CombinedDataAccessException; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; /** diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java index d491ac09..2f3a6237 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/convert/EntityRowMapperUnitTests.java @@ -44,7 +44,6 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.PersistenceConstructor; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; import org.springframework.data.relational.core.mapping.Embedded; import org.springframework.data.relational.core.mapping.NamingStrategy; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/MyBatisDataAccessStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategyUnitTests.java similarity index 94% rename from spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/MyBatisDataAccessStrategyUnitTests.java rename to spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategyUnitTests.java index 7e5ccab5..427c4e3f 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/MyBatisDataAccessStrategyUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategyUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 the original author or authors. + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.data.jdbc.core; +package org.springframework.data.jdbc.mybatis; import static java.util.Arrays.*; import static org.assertj.core.api.Assertions.*; @@ -26,9 +26,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; + +import org.springframework.data.jdbc.core.PropertyPathTestingUtils; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; -import org.springframework.data.jdbc.mybatis.MyBatisContext; -import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy; import org.springframework.data.mapping.PersistentPropertyPath; import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; @@ -37,6 +37,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp * Unit tests for the {@link MyBatisDataAccessStrategy}, mainly ensuring that the correct statements get's looked up. * * @author Jens Schauder + * @author Mark Paluch */ public class MyBatisDataAccessStrategyUnitTests { @@ -127,7 +128,7 @@ public class MyBatisDataAccessStrategyUnitTests { accessStrategy.deleteAll(path); verify(session).delete( - eq("org.springframework.data.jdbc.core.MyBatisDataAccessStrategyUnitTests$DummyEntityMapper.deleteAll-one-two"), + eq("org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategyUnitTests$DummyEntityMapper.deleteAll-one-two"), captor.capture()); assertThat(captor.getValue()) // @@ -173,7 +174,7 @@ public class MyBatisDataAccessStrategyUnitTests { accessStrategy.delete("rootid", path); verify(session).delete( - eq("org.springframework.data.jdbc.core.MyBatisDataAccessStrategyUnitTests$DummyEntityMapper.delete-one-two"), + eq("org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategyUnitTests$DummyEntityMapper.delete-one-two"), captor.capture()); assertThat(captor.getValue()) // diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java index e9115a7d..93046a7c 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java @@ -31,11 +31,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; -import org.springframework.data.jdbc.core.DataAccessStrategy; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories; import org.springframework.data.jdbc.testing.TestConfiguration; -import org.springframework.data.relational.core.conversion.RelationalConverter; import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.repository.CrudRepository; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/EnableJdbcRepositoriesIntegrationTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/EnableJdbcRepositoriesIntegrationTests.java index d2d085e4..e265f72d 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/EnableJdbcRepositoriesIntegrationTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/config/EnableJdbcRepositoriesIntegrationTests.java @@ -33,7 +33,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Id; -import org.springframework.data.jdbc.core.DataAccessStrategy; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.core.convert.SqlGeneratorSource; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java index b2ff30e9..99609987 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategyUnitTests.java @@ -15,9 +15,7 @@ */ package org.springframework.data.jdbc.repository.support; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.lang.reflect.Method; @@ -25,21 +23,18 @@ import java.text.NumberFormat; import org.junit.Before; import org.junit.Test; + import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.jdbc.core.DataAccessStrategy; -import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcConverter; import org.springframework.data.jdbc.repository.QueryMappingConfiguration; import org.springframework.data.jdbc.repository.config.DefaultQueryMappingConfiguration; import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.projection.ProjectionFactory; -import org.springframework.data.relational.core.conversion.BasicRelationalConverter; -import org.springframework.data.relational.core.conversion.RelationalConverter; import org.springframework.data.relational.core.mapping.RelationalMappingContext; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.RepositoryQuery; -import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.jdbc.core.namedparam.SqlParameterSource; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java index f4739514..723d8f28 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java @@ -26,13 +26,14 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; + import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.annotation.Id; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.JdbcTypeFactory; import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java index 8920571a..03b7773c 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java @@ -20,6 +20,7 @@ import java.util.Optional; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationEventPublisher; @@ -27,8 +28,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.convert.CustomConversions; -import org.springframework.data.jdbc.core.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.BasicJdbcConverter; +import org.springframework.data.jdbc.core.convert.DataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy; import org.springframework.data.jdbc.core.convert.DefaultJdbcTypeFactory; import org.springframework.data.jdbc.core.convert.JdbcConverter; diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java index 3833475d..6150a2c8 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/AggregateChange.java @@ -139,12 +139,12 @@ public class AggregateChange { private static PersistentPropertyAccessor setId(RelationalConverter converter, DbAction.WithDependingOn action, Object generatedId) { - Object originalElement = action.getEntity(); + T originalElement = action.getEntity(); RelationalPersistentEntity persistentEntity = (RelationalPersistentEntity) converter.getMappingContext() .getRequiredPersistentEntity(action.getEntityType()); PersistentPropertyAccessor intermediateAccessor = converter.getPropertyAccessor(persistentEntity, - (T) originalElement); + originalElement); RelationalPersistentProperty idProperty = persistentEntity.getIdProperty(); if (idProperty != null) { @@ -166,11 +166,11 @@ public class AggregateChange { ? converter.getPropertyAccessor(persistentEntity, entity) // : null; - actions.forEach(a -> { + actions.forEach(action -> { - a.executeWith(interpreter); + action.executeWith(interpreter); - processGeneratedId(context, converter, persistentEntity, propertyAccessor, a); + processGeneratedId(context, converter, persistentEntity, propertyAccessor, action); }); if (propertyAccessor != null) { @@ -183,25 +183,28 @@ public class AggregateChange { } private void processGeneratedId(RelationalMappingContext context, RelationalConverter converter, - RelationalPersistentEntity persistentEntity, PersistentPropertyAccessor propertyAccessor, DbAction a) { + @Nullable RelationalPersistentEntity persistentEntity, + @Nullable PersistentPropertyAccessor propertyAccessor, DbAction action) { - if (a instanceof DbAction.WithGeneratedId) { + if (!(action instanceof DbAction.WithGeneratedId)) { + return; + } - Assert.notNull(persistentEntity, - "For statements triggering database side id generation a RelationalPersistentEntity must be provided."); - Assert.notNull(propertyAccessor, "propertyAccessor must not be null"); + Assert.notNull(persistentEntity, + "For statements triggering database side id generation a RelationalPersistentEntity must be provided."); + Assert.notNull(propertyAccessor, "propertyAccessor must not be null"); - Object generatedId = ((DbAction.WithGeneratedId) a).getGeneratedId(); + Object generatedId = ((DbAction.WithGeneratedId) action).getGeneratedId(); - if (generatedId != null) { + if (generatedId == null) { + return; + } - if (a instanceof DbAction.InsertRoot && a.getEntityType().equals(entityType)) { - propertyAccessor.setProperty(persistentEntity.getRequiredIdProperty(), generatedId); - } else if (a instanceof DbAction.WithDependingOn) { + if (action instanceof DbAction.InsertRoot && action.getEntityType().equals(entityType)) { + propertyAccessor.setProperty(persistentEntity.getRequiredIdProperty(), generatedId); + } else if (action instanceof DbAction.WithDependingOn) { - setIdOfNonRootEntity(context, converter, propertyAccessor, (DbAction.WithDependingOn) a, generatedId); - } - } + setIdOfNonRootEntity(context, converter, propertyAccessor, (DbAction.WithDependingOn) action, generatedId); } }