Add Stream support to JdbcAggregateOperations

See #1714
Original pull request #1963

Signed-off-by: Sergey Korotaev <sergey.evgen.kor2501@gmail.com>
This commit is contained in:
Sergey Korotaev
2024-12-26 21:07:30 +03:00
committed by Jens Schauder
parent 4ef05389a7
commit ea296429df
11 changed files with 475 additions and 2 deletions

View File

@@ -27,8 +27,8 @@ import java.util.*;
import java.util.ArrayList;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
@@ -81,6 +81,7 @@ import org.springframework.test.context.ContextConfiguration;
* @author Mikhail Polivakha
* @author Chirag Tailor
* @author Vincent Galloy
* @author Sergey Korotaev
*/
@IntegrationTest
abstract class AbstractJdbcAggregateTemplateIntegrationTests {
@@ -309,6 +310,18 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
.containsExactly(tuple(legoSet.id, legoSet.manual.id, legoSet.manual.content));
}
@Test // GH-1714
void saveAndLoadManeEntitiesWithReferenceEntityLikeStream() {
template.save(legoSet);
Stream<LegoSet> streamable = template.streamAll(LegoSet.class);
assertThat(streamable)
.extracting("id", "manual.id", "manual.content") //
.containsExactly(tuple(legoSet.id, legoSet.manual.id, legoSet.manual.content));
}
@Test // DATAJDBC-101
void saveAndLoadManyEntitiesWithReferencedEntitySorted() {
@@ -323,6 +336,20 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
.containsExactly("Frozen", "Lava", "Star");
}
@Test // GH-1714
void saveAndLoadManyEntitiesWithReferencedEntitySortedLikeStream() {
template.save(createLegoSet("Lava"));
template.save(createLegoSet("Star"));
template.save(createLegoSet("Frozen"));
Stream<LegoSet> reloadedLegoSets = template.streamAll(LegoSet.class, Sort.by("name"));
assertThat(reloadedLegoSets) //
.extracting("name") //
.containsExactly("Frozen", "Lava", "Star");
}
@Test // DATAJDBC-101
void saveAndLoadManyEntitiesWithReferencedEntitySortedAndPaged() {
@@ -360,6 +387,12 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
.isInstanceOf(InvalidPersistentPropertyPath.class);
}
@Test // GH-1714
void findByNonPropertySortLikeStreamFails() {
assertThatThrownBy(() -> template.streamAll(LegoSet.class, Sort.by("somethingNotExistant")))
.isInstanceOf(InvalidPersistentPropertyPath.class);
}
@Test // DATAJDBC-112
void saveAndLoadManyEntitiesByIdWithReferencedEntity() {
@@ -371,6 +404,17 @@ abstract class AbstractJdbcAggregateTemplateIntegrationTests {
.contains(tuple(legoSet.id, legoSet.manual.id, legoSet.manual.content));
}
@Test // GH-1714
void saveAndLoadManyEntitiesByIdWithReferencedEntityLikeStream() {
template.save(legoSet);
Stream<LegoSet> reloadedLegoSets = template.streamAllByIds(singletonList(legoSet.id), LegoSet.class);
assertThat(reloadedLegoSets).hasSize(1).extracting("id", "manual.id", "manual.content")
.contains(tuple(legoSet.id, legoSet.manual.id, legoSet.manual.content));
}
@Test // DATAJDBC-112
void saveAndLoadAnEntityWithReferencedNullEntity() {

View File

@@ -22,7 +22,12 @@ import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.data.relational.core.sql.SqlIdentifier.*;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.session.SqlSession;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
@@ -43,6 +48,7 @@ import org.springframework.data.relational.core.mapping.RelationalPersistentProp
* @author Mark Paluch
* @author Tyler Van Gorder
* @author Chirag Tailor
* @author Sergey Korotaev
*/
public class MyBatisDataAccessStrategyUnitTests {
@@ -241,6 +247,36 @@ public class MyBatisDataAccessStrategyUnitTests {
);
}
@Test
public void streamAll() {
String value = "some answer";
Cursor<String> cursor = getCursor(value);
when(session.selectCursor(anyString(), any())).then(answer -> cursor);
Stream<String> streamable = accessStrategy.streamAll(String.class);
verify(session).selectCursor(eq("java.lang.StringMapper.streamAll"), captor.capture());
assertThat(streamable).isNotNull().containsExactly(value);
assertThat(captor.getValue()) //
.isNotNull() //
.extracting( //
MyBatisContext::getInstance, //
MyBatisContext::getId, //
MyBatisContext::getDomainType, //
c -> c.get("key") //
).containsExactly( //
null, //
null, //
String.class, //
null //
);
}
@Test // DATAJDBC-123
public void findAllById() {
@@ -263,6 +299,33 @@ public class MyBatisDataAccessStrategyUnitTests {
);
}
@Test
public void streamAllByIds() {
String value = "some answer 2";
Cursor<String> cursor = getCursor(value);
when(session.selectCursor(anyString(), any())).then(answer -> cursor);
accessStrategy.streamAllByIds(asList("id1", "id2"), String.class);
verify(session).selectCursor(eq("java.lang.StringMapper.streamAllByIds"), captor.capture());
assertThat(captor.getValue()) //
.isNotNull() //
.extracting( //
MyBatisContext::getInstance, //
MyBatisContext::getId, //
MyBatisContext::getDomainType, //
c -> c.get("key") //
).containsExactly( //
null, //
asList("id1", "id2"), //
String.class, //
null //
);
}
@SuppressWarnings("unchecked")
@Test // DATAJDBC-384
public void findAllByPath() {
@@ -367,6 +430,33 @@ public class MyBatisDataAccessStrategyUnitTests {
);
}
@Test
public void streamAllSorted() {
String value = "some answer 3";
Cursor<String> cursor = getCursor(value);
when(session.selectCursor(anyString(), any())).then(answer -> cursor);
accessStrategy.streamAll(String.class, Sort.by("length"));
verify(session).selectCursor(eq("java.lang.StringMapper.streamAllSorted"), captor.capture());
assertThat(captor.getValue()) //
.isNotNull() //
.extracting( //
MyBatisContext::getInstance, //
MyBatisContext::getId, //
MyBatisContext::getDomainType, //
c -> c.get("sort") //
).containsExactly( //
null, //
null, //
String.class, //
Sort.by("length") //
);
}
@Test // DATAJDBC-101
public void findAllPaged() {
@@ -399,5 +489,36 @@ public class MyBatisDataAccessStrategyUnitTests {
ChildTwo two;
}
private static class ChildTwo {}
private static class ChildTwo {
}
private Cursor<String> getCursor(String value) {
return new Cursor<>() {
@Override
public boolean isOpen() {
return false;
}
@Override
public boolean isConsumed() {
return false;
}
@Override
public int getCurrentIndex() {
return 0;
}
@Override
public void close() {
}
@NotNull
@Override
public Iterator<String> iterator() {
return List.of(value).iterator();
}
};
}
}