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.
This commit is contained in:
@@ -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<DataAccessStrategy> strategies;
|
||||
@Deprecated
|
||||
public class CascadingDataAccessStrategy
|
||||
extends org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy {
|
||||
|
||||
public CascadingDataAccessStrategy(List<DataAccessStrategy> 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 <T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> Object insert(T instance, Class<T> 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 <S> boolean update(S instance, Class<S> 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<RelationalPersistentProperty> propertyPath) {
|
||||
collectVoid(das -> das.delete(rootId, propertyPath));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> void deleteAll(Class<T> 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<RelationalPersistentProperty> 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> T findById(Object id, Class<T> domainType) {
|
||||
return collect(das -> das.findById(id, domainType));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> Iterable<T> findAll(Class<T> 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 <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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 <T> Iterable<T> 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 <T> boolean existsById(Object id, Class<T> domainType) {
|
||||
return collect(das -> das.existsById(id, domainType));
|
||||
}
|
||||
|
||||
private <T> T collect(Function<DataAccessStrategy, T> function) {
|
||||
|
||||
// Keep <T> as Eclipse fails to compile if <> is used.
|
||||
return strategies.stream().collect(new FunctionCollector<>(function));
|
||||
}
|
||||
|
||||
private void collectVoid(Consumer<DataAccessStrategy> consumer) {
|
||||
|
||||
collect(das -> {
|
||||
consumer.accept(das);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <T> 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
|
||||
<T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> the type of the instance.
|
||||
* @return the id generated by the database if any.
|
||||
* @since 1.1
|
||||
*/
|
||||
default <T> Object insert(T instance, Class<T> 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 <T> the type of the instance to save.
|
||||
* @return whether the update actually updated a row.
|
||||
*/
|
||||
<T> boolean update(T instance, Class<T> 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<RelationalPersistentProperty> 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 <T> type of the domain type.
|
||||
*/
|
||||
<T> void deleteAll(Class<T> 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<RelationalPersistentProperty> 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 <T> the type of the entity.
|
||||
* @return Might return {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
<T> T findById(Object id, Class<T> domainType);
|
||||
|
||||
/**
|
||||
* Loads all entities of the given type.
|
||||
*
|
||||
* @param domainType the type of entities to load. Must not be {@code null}.
|
||||
* @param <T> the type of entities to load.
|
||||
* @return Guaranteed to be not {@code null}.
|
||||
*/
|
||||
<T> Iterable<T> findAll(Class<T> 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 <T> type of entities to load.
|
||||
* @return the loaded entities. Guaranteed to be not {@code null}.
|
||||
*/
|
||||
<T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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.
|
||||
*/
|
||||
<T> Iterable<T> 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 <T> the type of the entity.
|
||||
* @return {@code true} if a matching row exists, otherwise {@code false}.
|
||||
*/
|
||||
<T> boolean existsById(Object id, Class<T> domainType);
|
||||
}
|
||||
@Deprecated
|
||||
public interface DataAccessStrategy extends org.springframework.data.jdbc.core.convert.DataAccessStrategy {}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> Object insert(T instance, Class<T> 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 <S> boolean update(S instance, Class<S> 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<RelationalPersistentProperty> 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 <T> void deleteAll(Class<T> domainType) {
|
||||
delegate.deleteAll(domainType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath)
|
||||
*/
|
||||
@Override
|
||||
public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> 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> T findById(Object id, Class<T> 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 <T> Iterable<T> findAll(Class<T> domainType) {
|
||||
return delegate.findAll(domainType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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 <T> Iterable<T> 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 <T> boolean existsById(Object id, Class<T> 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 {}
|
||||
|
||||
@@ -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<T> extends org.springframework.data.jdbc.core.convert.EntityRowMapper<T> {
|
||||
@@ -30,5 +30,4 @@ public class EntityRowMapper<T> extends org.springframework.data.jdbc.core.conve
|
||||
DataAccessStrategy accessStrategy) {
|
||||
super(entity, converter, accessStrategy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<T>(entity, accessStrategy, resultSet).mapRow();
|
||||
}
|
||||
|
||||
@Value
|
||||
private class ReadingContext<T> {
|
||||
|
||||
private final RelationalPersistentEntity<T> 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<RelationalPersistentEntity<?>, RelationalPersistentProperty>) getMappingContext(), entity);
|
||||
this.path = new PersistentPropertyPathExtension(
|
||||
(MappingContext<RelationalPersistentEntity<?>, RelationalPersistentProperty>) getMappingContext(), entity);
|
||||
}
|
||||
|
||||
public ReadingContext(RelationalPersistentEntity<T> entity, DataAccessStrategy accessStrategy, ResultSet resultSet, PersistentPropertyPathExtension path) {
|
||||
public ReadingContext(RelationalPersistentEntity<T> 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<Object, ?>) entity, instance);
|
||||
|
||||
for (RelationalPersistentProperty p : entity) {
|
||||
@@ -380,10 +378,8 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
|
||||
@Nullable
|
||||
private <S> S readEntityFrom(RelationalPersistentProperty property, PersistentPropertyPathExtension path) {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ReadingContext<S> newContext = extendBy(property);
|
||||
ReadingContext<?> newContext = extendBy(property);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
RelationalPersistentEntity<S> entity = (RelationalPersistentEntity<S>) getMappingContext()
|
||||
.getRequiredPersistentEntity(property.getActualType());
|
||||
|
||||
@@ -425,7 +421,7 @@ public class BasicJdbcConverter extends BasicRelationalConverter implements Jdbc
|
||||
|
||||
private <S> S createInstanceInternal(RelationalPersistentEntity<S> entity, @Nullable Object idValue) {
|
||||
|
||||
return createInstance(entity,parameter -> {
|
||||
return createInstance(entity, parameter -> {
|
||||
|
||||
String parameterName = parameter.getName();
|
||||
|
||||
|
||||
@@ -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<DataAccessStrategy> strategies;
|
||||
|
||||
public CascadingDataAccessStrategy(List<DataAccessStrategy> 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 <T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> Object insert(T instance, Class<T> 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 <S> boolean update(S instance, Class<S> 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<RelationalPersistentProperty> propertyPath) {
|
||||
collectVoid(das -> das.delete(rootId, propertyPath));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> void deleteAll(Class<T> 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<RelationalPersistentProperty> 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> T findById(Object id, Class<T> domainType) {
|
||||
return collect(das -> das.findById(id, domainType));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> Iterable<T> findAll(Class<T> 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 <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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 <T> Iterable<T> 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 <T> boolean existsById(Object id, Class<T> domainType) {
|
||||
return collect(das -> das.existsById(id, domainType));
|
||||
}
|
||||
|
||||
private <T> T collect(Function<DataAccessStrategy, T> function) {
|
||||
|
||||
// Keep <T> as Eclipse fails to compile if <> is used.
|
||||
return strategies.stream().collect(new FunctionCollector<>(function));
|
||||
}
|
||||
|
||||
private void collectVoid(Consumer<DataAccessStrategy> consumer) {
|
||||
|
||||
collect(das -> {
|
||||
consumer.accept(das);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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 <T> 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
|
||||
<T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> the type of the instance.
|
||||
* @return the id generated by the database if any.
|
||||
* @since 1.1
|
||||
*/
|
||||
default <T> Object insert(T instance, Class<T> 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 <T> the type of the instance to save.
|
||||
* @return whether the update actually updated a row.
|
||||
*/
|
||||
<T> boolean update(T instance, Class<T> 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<RelationalPersistentProperty> 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 <T> type of the domain type.
|
||||
*/
|
||||
<T> void deleteAll(Class<T> 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<RelationalPersistentProperty> 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 <T> the type of the entity.
|
||||
* @return Might return {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
<T> T findById(Object id, Class<T> domainType);
|
||||
|
||||
/**
|
||||
* Loads all entities of the given type.
|
||||
*
|
||||
* @param domainType the type of entities to load. Must not be {@code null}.
|
||||
* @param <T> the type of entities to load.
|
||||
* @return Guaranteed to be not {@code null}.
|
||||
*/
|
||||
<T> Iterable<T> findAll(Class<T> 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 <T> type of entities to load.
|
||||
* @return the loaded entities. Guaranteed to be not {@code null}.
|
||||
*/
|
||||
<T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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.
|
||||
*/
|
||||
<T> Iterable<T> 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 <T> the type of the entity.
|
||||
* @return {@code true} if a matching row exists, otherwise {@code false}.
|
||||
*/
|
||||
<T> boolean existsById(Object id, Class<T> domainType);
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 <T> Object insert(T instance, Class<T> domainType, Map<String, Object> 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 <T> Object insert(T instance, Class<T> 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 <S> boolean update(S instance, Class<S> 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<RelationalPersistentProperty> 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 <T> void deleteAll(Class<T> domainType) {
|
||||
delegate.deleteAll(domainType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath)
|
||||
*/
|
||||
@Override
|
||||
public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> 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> T findById(Object id, Class<T> 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 <T> Iterable<T> findAll(Class<T> domainType) {
|
||||
return delegate.findAll(domainType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> 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 <T> Iterable<T> 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 <T> boolean existsById(Object id, Class<T> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<T> implements RowMapper<T> {
|
||||
|
||||
|
||||
@@ -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<T> implements Collector<DataAccessStrategy, FunctionColl
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#supplier()
|
||||
*/
|
||||
@@ -52,7 +52,7 @@ class FunctionCollector<T> implements Collector<DataAccessStrategy, FunctionColl
|
||||
return ResultOrException::new;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#accumulator()
|
||||
*/
|
||||
@@ -72,7 +72,7 @@ class FunctionCollector<T> implements Collector<DataAccessStrategy, FunctionColl
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#combiner()
|
||||
*/
|
||||
@@ -84,7 +84,7 @@ class FunctionCollector<T> implements Collector<DataAccessStrategy, FunctionColl
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#finisher()
|
||||
*/
|
||||
@@ -101,7 +101,7 @@ class FunctionCollector<T> implements Collector<DataAccessStrategy, FunctionColl
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.util.stream.Collector#characteristics()
|
||||
*/
|
||||
@@ -15,14 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.core.convert;
|
||||
|
||||
import org.springframework.data.jdbc.core.DataAccessStrategy;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.springframework.data.relational.core.conversion.RelationalConverter;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
/**
|
||||
* A {@link JdbcConverter} is responsible for converting for values to the native relational representation and vice
|
||||
* versa.
|
||||
|
||||
@@ -114,10 +114,17 @@ class SqlGenerator {
|
||||
Column idColumn = subSelectTable.column(parentPath.getIdColumnName());
|
||||
Column selectFilterColumn = subSelectTable.column(parentPath.getEffectiveIdColumnName());
|
||||
|
||||
Condition innerCondition = parentPath.getLength() == 1 // if the parent is the root of the path
|
||||
? rootCondition.apply(selectFilterColumn) // apply the rootCondition
|
||||
: getSubselectCondition(parentPath, rootCondition, selectFilterColumn); // otherwise we need another layer of
|
||||
// subselect
|
||||
Condition innerCondition;
|
||||
|
||||
if (parentPath.getLength() == 1) { // if the parent is the root of the path
|
||||
|
||||
// apply the rootCondition
|
||||
innerCondition = rootCondition.apply(selectFilterColumn);
|
||||
} else {
|
||||
|
||||
// otherwise we need another layer of subselect
|
||||
innerCondition = getSubselectCondition(parentPath, rootCondition, selectFilterColumn);
|
||||
}
|
||||
|
||||
Select select = Select.builder() //
|
||||
.select(idColumn) //
|
||||
|
||||
@@ -22,10 +22,11 @@ import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.data.jdbc.core.CascadingDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy;
|
||||
|
||||
import org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.DefaultDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.DelegatingDataAccessStrategy;
|
||||
import org.springframework.data.jdbc.core.convert.JdbcConverter;
|
||||
import org.springframework.data.jdbc.core.convert.SqlGeneratorSource;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
@@ -101,8 +102,7 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
|
||||
* <p>
|
||||
* 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}.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<T extends Repository<S, ID>, S, ID extends Serializable> //
|
||||
public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
|
||||
@@ -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()) //
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -139,12 +139,12 @@ public class AggregateChange<T> {
|
||||
private static <T> PersistentPropertyAccessor<T> setId(RelationalConverter converter,
|
||||
DbAction.WithDependingOn<T> action, Object generatedId) {
|
||||
|
||||
Object originalElement = action.getEntity();
|
||||
T originalElement = action.getEntity();
|
||||
|
||||
RelationalPersistentEntity<T> persistentEntity = (RelationalPersistentEntity<T>) converter.getMappingContext()
|
||||
.getRequiredPersistentEntity(action.getEntityType());
|
||||
PersistentPropertyAccessor<T> intermediateAccessor = converter.getPropertyAccessor(persistentEntity,
|
||||
(T) originalElement);
|
||||
originalElement);
|
||||
|
||||
RelationalPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
if (idProperty != null) {
|
||||
@@ -166,11 +166,11 @@ public class AggregateChange<T> {
|
||||
? 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<T> {
|
||||
}
|
||||
|
||||
private void processGeneratedId(RelationalMappingContext context, RelationalConverter converter,
|
||||
RelationalPersistentEntity<T> persistentEntity, PersistentPropertyAccessor<T> propertyAccessor, DbAction<?> a) {
|
||||
@Nullable RelationalPersistentEntity<T> persistentEntity,
|
||||
@Nullable PersistentPropertyAccessor<T> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user