Skip to content

Commit d450168

Browse files
authored
Merge pull request #244 from kazuki43zoo/gh-21_item-to-paramater
Support converting item to parameter object
2 parents 0280442 + c5883dc commit d450168

File tree

4 files changed

+134
-4
lines changed

4 files changed

+134
-4
lines changed

src/main/java/org/mybatis/spring/batch/MyBatisBatchItemWriter.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.mybatis.spring.SqlSessionTemplate;
3030
import org.springframework.batch.item.ItemWriter;
3131
import org.springframework.beans.factory.InitializingBean;
32+
import org.springframework.core.convert.converter.Converter;
3233
import org.springframework.dao.EmptyResultDataAccessException;
3334
import org.springframework.dao.InvalidDataAccessResourceUsageException;
3435

@@ -62,6 +63,8 @@ public class MyBatisBatchItemWriter<T> implements ItemWriter<T>, InitializingBea
6263

6364
private boolean assertUpdates = true;
6465

66+
private Converter<T, ?> itemToParameterConverter = new PassThroughConverter<>();
67+
6568
/**
6669
* Public setter for the flag that determines whether an assertion is made
6770
* that all items cause at least one row to be updated.
@@ -102,6 +105,18 @@ public void setStatementId(String statementId) {
102105
this.statementId = statementId;
103106
}
104107

108+
/**
109+
* Public setter for a converter that converting item to parameter object.
110+
* <p>
111+
* By default implementation, an item does not convert.
112+
*
113+
* @param itemToParameterConverter a converter that converting item to parameter object
114+
* @since 2.0.0
115+
*/
116+
public void setItemToParameterConverter(Converter<T, ?> itemToParameterConverter) {
117+
this.itemToParameterConverter = itemToParameterConverter;
118+
}
119+
105120
/**
106121
* Check mandatory properties - there must be an SqlSession and a statementId.
107122
*/
@@ -110,6 +125,7 @@ public void afterPropertiesSet() {
110125
notNull(sqlSessionTemplate, "A SqlSessionFactory or a SqlSessionTemplate is required.");
111126
isTrue(ExecutorType.BATCH == sqlSessionTemplate.getExecutorType(), "SqlSessionTemplate's executor type must be BATCH");
112127
notNull(statementId, "A statementId is required.");
128+
notNull(itemToParameterConverter, "A itemToParameterConverter is required.");
113129
}
114130

115131
/**
@@ -122,7 +138,7 @@ public void write(final List<? extends T> items) {
122138
LOGGER.debug(() -> "Executing batch with " + items.size() + " items.");
123139

124140
for (T item : items) {
125-
sqlSessionTemplate.update(statementId, item);
141+
sqlSessionTemplate.update(statementId, itemToParameterConverter.convert(item));
126142
}
127143

128144
List<BatchResult> results = sqlSessionTemplate.flushStatements();
@@ -146,4 +162,13 @@ public void write(final List<? extends T> items) {
146162
}
147163
}
148164

165+
private static class PassThroughConverter<T> implements Converter<T, T> {
166+
167+
@Override
168+
public T convert(T source) {
169+
return source;
170+
}
171+
172+
}
173+
149174
}

src/main/java/org/mybatis/spring/batch/builder/MyBatisBatchItemWriterBuilder.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.apache.ibatis.session.SqlSessionFactory;
1919
import org.mybatis.spring.SqlSessionTemplate;
2020
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
21+
import org.springframework.core.convert.converter.Converter;
2122

2223
/**
2324
* A builder for the {@link MyBatisBatchItemWriter}.
@@ -32,6 +33,7 @@ public class MyBatisBatchItemWriterBuilder<T> {
3233
private SqlSessionFactory sqlSessionFactory;
3334
private String statementId;
3435
private Boolean assertUpdates;
36+
private Converter<T, ?> itemToParameterConverter;
3537

3638
/**
3739
* Set the {@link SqlSessionTemplate} to be used by writer for database access.
@@ -83,6 +85,18 @@ public MyBatisBatchItemWriterBuilder<T> assertUpdates(boolean assertUpdates) {
8385
return this;
8486
}
8587

88+
/**
89+
* Set a converter that converting item to parameter object.
90+
*
91+
* @param itemToParameterConverter a converter that converting item to parameter object
92+
* @return this instance for method chaining
93+
* @see MyBatisBatchItemWriter#setItemToParameterConverter(Converter)
94+
*/
95+
public MyBatisBatchItemWriterBuilder<T> itemToParameterConverter(Converter<T, ?> itemToParameterConverter) {
96+
this.itemToParameterConverter = itemToParameterConverter;
97+
return this;
98+
}
99+
86100
/**
87101
* Returns a fully built {@link MyBatisBatchItemWriter}.
88102
*
@@ -96,6 +110,9 @@ public MyBatisBatchItemWriter<T> build() {
96110
if (this.assertUpdates != null) {
97111
writer.setAssertUpdates(this.assertUpdates);
98112
}
113+
if (this.itemToParameterConverter != null) {
114+
writer.setItemToParameterConverter(this.itemToParameterConverter);
115+
}
99116
return writer;
100117
}
101118

src/test/java/org/mybatis/spring/batch/MyBatisBatchItemWriterTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,28 @@
1616
package org.mybatis.spring.batch;
1717

1818
import org.apache.ibatis.executor.BatchResult;
19+
import org.apache.ibatis.session.ExecutorType;
1920
import org.assertj.core.util.Lists;
2021
import org.junit.jupiter.api.BeforeEach;
2122
import org.junit.jupiter.api.Test;
2223
import org.mockito.InjectMocks;
2324
import org.mockito.Mock;
25+
import org.mockito.Mockito;
2426
import org.mockito.MockitoAnnotations;
2527
import org.mybatis.spring.SqlSessionTemplate;
2628
import org.mybatis.spring.batch.domain.Employee;
2729
import org.springframework.dao.EmptyResultDataAccessException;
2830
import org.springframework.dao.InvalidDataAccessResourceUsageException;
2931

32+
import java.time.Clock;
33+
import java.time.Instant;
34+
import java.time.LocalDateTime;
35+
import java.time.ZoneId;
3036
import java.util.Arrays;
3137
import java.util.Collections;
38+
import java.util.HashMap;
3239
import java.util.List;
40+
import java.util.Map;
3341

3442
import static org.junit.jupiter.api.Assertions.assertThrows;
3543
import static org.mockito.BDDMockito.*;
@@ -77,4 +85,50 @@ void testZeroUpdateCountShouldThrowException() {
7785
);
7886
}
7987

88+
@Test
89+
void testItemToParameterConverterIsDefault() {
90+
this.writer.setAssertUpdates(false);
91+
this.writer.setStatementId("updateEmployee");
92+
93+
Employee employee = new Employee();
94+
List<Employee> employees = Collections.singletonList(employee);
95+
writer.write(employees);
96+
97+
Mockito.verify(this.mockSqlSessionTemplate).update("updateEmployee", employee);
98+
}
99+
100+
@Test
101+
void testSetItemToParameterConverter() {
102+
this.writer.setAssertUpdates(false);
103+
this.writer.setStatementId("updateEmployee");
104+
this.writer.setItemToParameterConverter(item -> {
105+
Map<String, Object> parameter = new HashMap<>();
106+
parameter.put("item", item);
107+
parameter.put("now",
108+
LocalDateTime.now(Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault())));
109+
return parameter;
110+
});
111+
112+
Employee employee = new Employee();
113+
List<Employee> employees = Collections.singletonList(employee);
114+
writer.write(employees);
115+
116+
Map<String, Object> parameter = new HashMap<>();
117+
parameter.put("item", employee);
118+
parameter.put("now",
119+
LocalDateTime.now(Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault())));
120+
Mockito.verify(this.mockSqlSessionTemplate).update("updateEmployee", parameter);
121+
}
122+
123+
@Test
124+
void testItemToParameterConverterIsNull() {
125+
given(mockSqlSessionTemplate.getExecutorType()).willReturn(ExecutorType.BATCH);
126+
this.writer.setStatementId("updateEmployee");
127+
writer.setItemToParameterConverter(null);
128+
129+
assertThrows(IllegalArgumentException.class, () -> writer.afterPropertiesSet(),
130+
"A itemToParameterConverter is required.");
131+
132+
}
133+
80134
}

src/test/java/org/mybatis/spring/batch/builder/MyBatisBatchItemWriterBuilderTest.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
3232

3333
import javax.sql.DataSource;
34-
import java.util.Arrays;
35-
import java.util.Collections;
36-
import java.util.List;
34+
import java.time.Clock;
35+
import java.time.Instant;
36+
import java.time.LocalDateTime;
37+
import java.time.ZoneId;
38+
import java.util.*;
3739

3840
/**
3941
* Tests for {@link MyBatisBatchItemWriterBuilder}.
@@ -137,6 +139,38 @@ void testConfigurationAssertUpdatesIsFalse() {
137139

138140
}
139141

142+
@Test
143+
void testConfigurationSetItemToParameterConverter() {
144+
145+
// @formatter:off
146+
MyBatisBatchItemWriter<Foo> itemWriter = new MyBatisBatchItemWriterBuilder<Foo>()
147+
.sqlSessionFactory(this.sqlSessionFactory)
148+
.statementId("updateFoo")
149+
.itemToParameterConverter(item -> {
150+
Map<String, Object> parameter = new HashMap<>();
151+
parameter.put("item", item);
152+
parameter.put("now", LocalDateTime.now(Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault())));
153+
return parameter;
154+
})
155+
.build();
156+
// @formatter:on
157+
itemWriter.afterPropertiesSet();
158+
159+
List<Foo> foos = getFoos();
160+
161+
itemWriter.write(foos);
162+
163+
Map<String, Object> parameter = new HashMap<>();
164+
parameter.put("now",
165+
LocalDateTime.now(Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault())));
166+
parameter.put("item", foos.get(0));
167+
Mockito.verify(this.sqlSession).update("updateFoo", parameter);
168+
parameter.put("item", foos.get(1));
169+
Mockito.verify(this.sqlSession).update("updateFoo", parameter);
170+
parameter.put("item", foos.get(2));
171+
Mockito.verify(this.sqlSession).update("updateFoo", parameter);
172+
}
173+
140174
private List<Foo> getFoos() {
141175
return Arrays.asList(new Foo("foo1"), new Foo("foo2"), new Foo("foo3"));
142176
}

0 commit comments

Comments
 (0)