Introducing AfterConvertCallback/Event.
This is to replace the AfterLoadCallback/Event in order to match the naming of other store modules. AfterLoadCallback/Event is still in place for now, but deprecated. Closes #1053 Original pull request: #1060.
This commit is contained in:
committed by
Mark Paluch
parent
b02ee3c083
commit
3cd25ee01f
@@ -208,7 +208,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
|
||||
T entity = accessStrategy.findById(id, domainType);
|
||||
if (entity != null) {
|
||||
return triggerAfterLoad(entity);
|
||||
return triggerAfterConvert(entity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
@@ -236,7 +236,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
Assert.notNull(domainType, "Domain type must not be null!");
|
||||
|
||||
Iterable<T> all = accessStrategy.findAll(domainType, sort);
|
||||
return triggerAfterLoad(all);
|
||||
return triggerAfterConvert(all);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -248,7 +248,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
|
||||
Assert.notNull(domainType, "Domain type must not be null!");
|
||||
|
||||
Iterable<T> items = triggerAfterLoad(accessStrategy.findAll(domainType, pageable));
|
||||
Iterable<T> items = triggerAfterConvert(accessStrategy.findAll(domainType, pageable));
|
||||
List<T> content = StreamSupport.stream(items.spliterator(), false).collect(Collectors.toList());
|
||||
|
||||
return PageableExecutionUtils.getPage(content, pageable, () -> accessStrategy.count(domainType));
|
||||
@@ -264,7 +264,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
Assert.notNull(domainType, "Domain type must not be null!");
|
||||
|
||||
Iterable<T> all = accessStrategy.findAll(domainType);
|
||||
return triggerAfterLoad(all);
|
||||
return triggerAfterConvert(all);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -278,7 +278,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
Assert.notNull(domainType, "Domain type must not be null!");
|
||||
|
||||
Iterable<T> allById = accessStrategy.findAllById(ids, domainType);
|
||||
return triggerAfterLoad(allById);
|
||||
return triggerAfterConvert(allById);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -385,22 +385,24 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
|
||||
return aggregateChange;
|
||||
}
|
||||
|
||||
private <T> Iterable<T> triggerAfterLoad(Iterable<T> all) {
|
||||
private <T> Iterable<T> triggerAfterConvert(Iterable<T> all) {
|
||||
|
||||
List<T> result = new ArrayList<>();
|
||||
|
||||
for (T e : all) {
|
||||
result.add(triggerAfterLoad(e));
|
||||
result.add(triggerAfterConvert(e));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private <T> T triggerAfterLoad(T entity) {
|
||||
private <T> T triggerAfterConvert(T entity) {
|
||||
|
||||
publisher.publishEvent(new AfterLoadEvent<>(entity));
|
||||
publisher.publishEvent(new AfterConvertEvent<>(entity));
|
||||
|
||||
return entityCallbacks.callback(AfterLoadCallback.class, entity);
|
||||
entity = entityCallbacks.callback(AfterLoadCallback.class, entity);
|
||||
return entityCallbacks.callback(AfterConvertCallback.class, entity);
|
||||
}
|
||||
|
||||
private <T> T triggerBeforeConvert(T aggregateRoot) {
|
||||
|
||||
@@ -32,6 +32,8 @@ import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
@@ -157,9 +159,11 @@ class JdbcQueryLookupStrategy implements QueryLookupStrategy {
|
||||
if (entity != null) {
|
||||
|
||||
publisher.publishEvent(new AfterLoadEvent<>(entity));
|
||||
publisher.publishEvent(new AfterConvertEvent<>(entity));
|
||||
|
||||
if (callbacks != null) {
|
||||
return callbacks.callback(AfterLoadCallback.class, entity);
|
||||
entity = callbacks.callback(AfterLoadCallback.class, entity);
|
||||
return callbacks.callback(AfterConvertCallback.class, entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import org.springframework.data.relational.core.conversion.MutableAggregateChang
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
import org.springframework.data.relational.core.mapping.NamingStrategy;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterDeleteCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterLoadCallback;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterSaveCallback;
|
||||
@@ -136,7 +137,9 @@ public class JdbcAggregateTemplateUnitTests {
|
||||
when(dataAccessStrategy.findAll(SampleEntity.class)).thenReturn(asList(alfred1, neumann1));
|
||||
|
||||
when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);
|
||||
|
||||
Iterable<SampleEntity> all = template.findAll(SampleEntity.class);
|
||||
|
||||
@@ -158,12 +161,16 @@ public class JdbcAggregateTemplateUnitTests {
|
||||
when(dataAccessStrategy.findAll(SampleEntity.class, Sort.by("name"))).thenReturn(asList(alfred1, neumann1));
|
||||
|
||||
when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);
|
||||
|
||||
Iterable<SampleEntity> all = template.findAll(SampleEntity.class, Sort.by("name"));
|
||||
|
||||
verify(callbacks).callback(AfterLoadCallback.class, alfred1);
|
||||
verify(callbacks).callback(AfterConvertCallback.class, alfred2);
|
||||
verify(callbacks).callback(AfterLoadCallback.class, neumann1);
|
||||
verify(callbacks).callback(AfterConvertCallback.class, neumann2);
|
||||
|
||||
assertThat(all).containsExactly(alfred2, neumann2);
|
||||
}
|
||||
@@ -180,12 +187,16 @@ public class JdbcAggregateTemplateUnitTests {
|
||||
when(dataAccessStrategy.findAll(SampleEntity.class, PageRequest.of(0, 20))).thenReturn(asList(alfred1, neumann1));
|
||||
|
||||
when(callbacks.callback(any(Class.class), eq(alfred1), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(alfred2), any())).thenReturn(alfred2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann1), any())).thenReturn(neumann2);
|
||||
when(callbacks.callback(any(Class.class), eq(neumann2), any())).thenReturn(neumann2);
|
||||
|
||||
Iterable<SampleEntity> all = template.findAll(SampleEntity.class, PageRequest.of(0, 20));
|
||||
|
||||
verify(callbacks).callback(AfterLoadCallback.class, alfred1);
|
||||
verify(callbacks).callback(AfterConvertCallback.class, alfred2);
|
||||
verify(callbacks).callback(AfterLoadCallback.class, neumann1);
|
||||
verify(callbacks).callback(AfterConvertCallback.class, neumann2);
|
||||
|
||||
assertThat(all).containsExactly(alfred2, neumann2);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import org.springframework.data.jdbc.testing.EnabledOnFeature;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
import org.springframework.data.jdbc.testing.TestDatabaseFeatures;
|
||||
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
@@ -309,7 +310,7 @@ public class JdbcRepositoryIntegrationTests {
|
||||
|
||||
repository.findAllWithSql();
|
||||
|
||||
assertThat(eventListener.events).hasSize(1).hasOnlyElementsOfType(AfterLoadEvent.class);
|
||||
assertThat(eventListener.events).hasSize(2).hasOnlyElementsOfTypes(AfterLoadEvent.class, AfterConvertEvent.class);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-318
|
||||
|
||||
@@ -51,15 +51,7 @@ import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.dialect.H2Dialect;
|
||||
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterDeleteEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.Identifier;
|
||||
import org.springframework.data.relational.core.mapping.event.RelationalEvent;
|
||||
import org.springframework.data.relational.core.mapping.event.WithId;
|
||||
import org.springframework.data.relational.core.mapping.event.*;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.jdbc.core.JdbcOperations;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
|
||||
@@ -198,7 +190,9 @@ public class SimpleJdbcRepositoryEventsUnitTests {
|
||||
.extracting(e -> (Class) e.getClass()) //
|
||||
.containsExactly( //
|
||||
AfterLoadEvent.class, //
|
||||
AfterLoadEvent.class //
|
||||
AfterConvertEvent.class, //
|
||||
AfterLoadEvent.class, //
|
||||
AfterConvertEvent.class //
|
||||
);
|
||||
}
|
||||
|
||||
@@ -217,7 +211,9 @@ public class SimpleJdbcRepositoryEventsUnitTests {
|
||||
.extracting(e -> (Class) e.getClass()) //
|
||||
.containsExactly( //
|
||||
AfterLoadEvent.class, //
|
||||
AfterLoadEvent.class //
|
||||
AfterConvertEvent.class, //
|
||||
AfterLoadEvent.class, //
|
||||
AfterConvertEvent.class //
|
||||
);
|
||||
}
|
||||
|
||||
@@ -234,7 +230,8 @@ public class SimpleJdbcRepositoryEventsUnitTests {
|
||||
assertThat(publisher.events) //
|
||||
.extracting(e -> (Class) e.getClass()) //
|
||||
.containsExactly( //
|
||||
AfterLoadEvent.class //
|
||||
AfterLoadEvent.class, //
|
||||
AfterConvertEvent.class //
|
||||
);
|
||||
}
|
||||
|
||||
@@ -253,7 +250,9 @@ public class SimpleJdbcRepositoryEventsUnitTests {
|
||||
.extracting(e -> (Class) e.getClass()) //
|
||||
.containsExactly( //
|
||||
AfterLoadEvent.class, //
|
||||
AfterLoadEvent.class //
|
||||
AfterConvertEvent.class, //
|
||||
AfterLoadEvent.class, //
|
||||
AfterConvertEvent.class //
|
||||
);
|
||||
}
|
||||
|
||||
@@ -273,7 +272,9 @@ public class SimpleJdbcRepositoryEventsUnitTests {
|
||||
.extracting(e -> (Class) e.getClass()) //
|
||||
.containsExactly( //
|
||||
AfterLoadEvent.class, //
|
||||
AfterLoadEvent.class //
|
||||
AfterConvertEvent.class, //
|
||||
AfterLoadEvent.class, //
|
||||
AfterConvertEvent.class //
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ public class AbstractRelationalEventListener<E> implements ApplicationListener<A
|
||||
|
||||
if (event instanceof AfterLoadEvent) {
|
||||
onAfterLoad((AfterLoadEvent<E>) event);
|
||||
} else if (event instanceof AfterConvertEvent) {
|
||||
onAfterConvert((AfterConvertEvent<E>) event);
|
||||
} else if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete((AfterDeleteEvent<E>) event);
|
||||
} else if (event instanceof AfterSaveEvent) {
|
||||
@@ -110,6 +112,7 @@ public class AbstractRelationalEventListener<E> implements ApplicationListener<A
|
||||
* Captures {@link AfterLoadEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
* @deprecated use {@link #onAfterConvert(AfterConvertEvent)} instead.
|
||||
*/
|
||||
protected void onAfterLoad(AfterLoadEvent<E> event) {
|
||||
|
||||
@@ -118,6 +121,18 @@ public class AbstractRelationalEventListener<E> implements ApplicationListener<A
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterConvertEvent}.
|
||||
*
|
||||
* @param event will never be {@literal null}.
|
||||
*/
|
||||
protected void onAfterConvert(AfterConvertEvent<E> event) {
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert({})", event.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures {@link AfterDeleteEvent}.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2019-2021 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.relational.core.mapping.event;
|
||||
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
|
||||
/**
|
||||
* An {@link EntityCallback} that gets invoked after an aggregate was converted from the database into an entity.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.6
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AfterConvertCallback<T> extends EntityCallback<T> {
|
||||
|
||||
/**
|
||||
* Entity callback method invoked after an aggregate root was converted. Can return either the same or a modified
|
||||
* instance of the domain object.
|
||||
*
|
||||
* @param aggregate the converted aggregate.
|
||||
* @return the converted and possibly modified aggregate.
|
||||
*/
|
||||
T onAfterConvert(T aggregate);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2017-2021 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.relational.core.mapping.event;
|
||||
|
||||
/**
|
||||
* Gets published after instantiation and setting of all the properties of an entity. This allows to do some
|
||||
* postprocessing of entities if the entities are mutable. For immutable entities use {@link AfterConvertCallback}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @since 2.6
|
||||
*/
|
||||
public class AfterConvertEvent<E> extends RelationalEventWithEntity<E> {
|
||||
|
||||
private static final long serialVersionUID = 7343072117054666699L;
|
||||
|
||||
/**
|
||||
* @param entity the newly instantiated entity. Must not be {@literal null}.
|
||||
*/
|
||||
public AfterConvertEvent(E entity) {
|
||||
super(entity);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@ import org.springframework.data.mapping.callback.EntityCallback;
|
||||
* @author Jens Schauder
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @deprecated Use {@link AfterConvertCallback} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@FunctionalInterface
|
||||
public interface AfterLoadCallback<T> extends EntityCallback<T> {
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ package org.springframework.data.relational.core.mapping.event;
|
||||
* postprocessing of entities if the entities are mutable. For immutable entities use {@link AfterLoadCallback}.
|
||||
*
|
||||
* @author Jens Schauder
|
||||
* @deprecated Use {@link AfterConvertEvent} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AfterLoadEvent<E> extends RelationalEventWithEntity<E> {
|
||||
|
||||
private static final long serialVersionUID = 7343072117054666699L;
|
||||
|
||||
@@ -43,6 +43,14 @@ public class AbstractRelationalEventListenerUnitTests {
|
||||
assertThat(events).containsExactly("afterLoad");
|
||||
}
|
||||
|
||||
@Test // GH-1053
|
||||
public void afterConvert() {
|
||||
|
||||
listener.onApplicationEvent(new AfterConvertEvent<>(dummyEntity));
|
||||
|
||||
assertThat(events).containsExactly("afterConvert");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-454
|
||||
public void beforeConvert() {
|
||||
|
||||
@@ -122,6 +130,11 @@ public class AbstractRelationalEventListenerUnitTests {
|
||||
events.add("afterLoad");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterConvert(AfterConvertEvent<DummyEntity> event) {
|
||||
events.add("afterConvert");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterDelete(AfterDeleteEvent<DummyEntity> event) {
|
||||
events.add("afterDelete");
|
||||
|
||||
@@ -871,6 +871,9 @@ The following table describes the available events:
|
||||
| After an aggregate root gets saved (that is, inserted or updated).
|
||||
|
||||
| {javadoc-base}org/springframework/data/relational/core/mapping/event/AfterLoadEvent.html[`AfterLoadEvent`]
|
||||
| After an aggregate root gets created from a database `ResultSet` and all its properties get set. _Note: This is deprecated. Use `AfterConvert` instead_
|
||||
|
||||
| {javadoc-base}org/springframework/data/relational/core/mapping/event/AfterConvertEvent.html[`AfterConvertEvent`]
|
||||
| After an aggregate root gets created from a database `ResultSet` and all its properties get set.
|
||||
|===
|
||||
|
||||
@@ -903,6 +906,9 @@ This is the correct callback if you want to set an id programmatically.
|
||||
| After an aggregate root gets saved (that is, inserted or updated).
|
||||
|
||||
| {javadoc-base}org/springframework/data/relational/core/mapping/event/AfterLoadCallback.html[`AfterLoadCallback`]
|
||||
| After an aggregate root gets created from a database `ResultSet` and all its property get set. _This is deprecated, use `AfterConvertCallback` instead_
|
||||
|
||||
| {javadoc-base}org/springframework/data/relational/core/mapping/event/AfterConvertCallback.html[`AfterConvertCallback`]
|
||||
| After an aggregate root gets created from a database `ResultSet` and all its property get set.
|
||||
|===
|
||||
|
||||
|
||||
Reference in New Issue
Block a user