Tagged: cursor
A lesson of @Transactional
Recently, I needed to work with a Cursor for statistics.
<mapper ...> <select id="selectCorsor" resultOrdered="true"> </select> </mapper>
It didn’t make any difference.
@Mapper public interface SomeMapper { Cursor<Some> selectCursor(...); }
We need the @Transactional
annotation for working with Cursor
.
@Service public class SomeService { @Transactional public <R> R applyCursor( ..., final Function<Cursor<Some>, R> function) { return function.apply(someMapper.selectCursor(..)); } @Autowired private SomeMapper someMapper; }
Well the method worked as expected.
The problem arose when I added a method using the origin method.
public void acceptEach( ..., final Consumer<Some> consumer) { applyCursor( ..., cursor -> { cursor.forEach(consumer::accept); return null; } ); }
This auxiliary method was not annotated with @Transactional
and it didn’t work.
And I found @Transactional method calling another method without @Transactional anotation?.
The acceptEach
method was also required to be annotated with @Transactional
.
Using Cursors with MyBatis
There are queries that you shouldn’t map as List<T>
.
And the Cursor
comes to play.
@Service public class SomeService { public Cursor<Some> getCursor(...) { // returns the cursor? } }
Well it not a good way to do with it. The return value Cursor<Some>
won’t work because the session may already be finished when the method returns.
@Service public class SomeService { @Transactional public <R> R applyCursor( ..., Function<Cursor<Some>, R> function) { final Cursor<Some> cursor = ...; return function.apply(cursor); } }
Now we can add some other methods to do with it.
public <R> R applyIterator( ..., Function<Iterator<Some>, R> function) { applyCursor( ..., cursor -> function.apply(cursor.iterator()) ); }
What about a Spliterator
?
public <R> R applySpliterator( ..., Function<Spliterator<Some>, R> function) { applyIterator( ..., iterator -> { int characteristics = Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED; Spliterator<CsEventAssociate> spliterator = Spliterators.spliteratorUnknownSize( iterator, characteristics); return function.apply(spliterator); } ); }
And the Stream
?
public <R> R applyStream( ..., Function<Stream<Some>, R> function) { return applySpliterator( ..., spliterator -> function.apply(StreamSupport.stream(spliterator, false)) ); }