diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java index 6e4fc2a78..2cc27ec9a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/HibernateItemWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2013 the original author or authors. + * Copyright 2006-2017 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. @@ -50,7 +50,6 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { protected static final Log logger = LogFactory .getLog(HibernateItemWriter.class); - private HibernateOperations hibernateTemplate; private SessionFactory sessionFactory; private boolean clearSession = true; @@ -66,18 +65,6 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { this.clearSession = clearSession; } - /** - * Public setter for the {@link HibernateOperations} property. - * - * @param hibernateTemplate - * the hibernateTemplate to set - * @deprecated As of 2.2 in favor of using Hibernate's session management APIs directly - */ - @Deprecated - public void setHibernateTemplate(HibernateOperations hibernateTemplate) { - this.hibernateTemplate = hibernateTemplate; - } - /** * Set the Hibernate SessionFactory to be used internally. * @@ -88,12 +75,12 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { } /** - * Check mandatory properties - there must be a hibernateTemplate. + * Check mandatory properties - there must be a sessionFactory. */ @Override public void afterPropertiesSet() { - Assert.state(!(hibernateTemplate == null && sessionFactory == null), - "Either HibernateOperations or SessionFactory must be provided"); + Assert.state(sessionFactory != null, + "SessionFactory must be provided"); } /** @@ -104,19 +91,10 @@ public class HibernateItemWriter implements ItemWriter, InitializingBean { */ @Override public void write(List items) { - if(sessionFactory == null) { - doWrite(hibernateTemplate, items); - hibernateTemplate.flush(); - if (clearSession) { - hibernateTemplate.clear(); - } - } - else { - doWrite(sessionFactory, items); - sessionFactory.getCurrentSession().flush(); - if(clearSession) { - sessionFactory.getCurrentSession().clear(); - } + doWrite(sessionFactory, items); + sessionFactory.getCurrentSession().flush(); + if(clearSession) { + sessionFactory.getCurrentSession().clear(); } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java new file mode 100644 index 000000000..0173896c6 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilder.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017 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 + * + * http://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.batch.item.database.builder; + +import org.hibernate.SessionFactory; + +import org.springframework.batch.item.database.HibernateItemWriter; +import org.springframework.util.Assert; + +/** + * A builder for the {@link HibernateItemWriter} + * + * @author Michael Minella + * @since 4.0 + * @see HibernateItemWriter + */ +public class HibernateItemWriterBuilder { + + private boolean clearSession = true; + + private SessionFactory sessionFactory; + + /** + * If set to false, the {@link org.hibernate.Session} will not be cleared at the end + * of the chunk. + * + * @param clearSession defaults to true + * @return this instance for method chaining + * @see HibernateItemWriter#setClearSession(boolean) + */ + public HibernateItemWriterBuilder clearSession(boolean clearSession) { + this.clearSession = clearSession; + + return this; + } + + /** + * The Hibernate {@link SessionFactory} to obtain a session from. Required. + * + * @param sessionFactory the {@link SessionFactory} + * @return this instance for method chaining + * @see HibernateItemWriter#setSessionFactory(SessionFactory) + */ + public HibernateItemWriterBuilder sessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + + return this; + } + + /** + * Returns a fully built {@link HibernateItemWriter} + * + * @return the writer + */ + public HibernateItemWriter build() { + Assert.state(this.sessionFactory != null, + "SessionFactory must be provided"); + + HibernateItemWriter writer = new HibernateItemWriter<>(); + writer.setSessionFactory(this.sessionFactory); + writer.setClearSession(this.clearSession); + + return writer; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java index 96349656d..85144b249 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java @@ -24,8 +24,6 @@ import org.hibernate.SessionFactory; import org.junit.Before; import org.junit.Test; -import org.springframework.orm.hibernate5.HibernateOperations; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -40,8 +38,6 @@ import static org.mockito.Mockito.when; */ public class HibernateItemWriterTests { - HibernateOperations ht; - HibernateItemWriter writer; SessionFactory factory; @@ -49,10 +45,11 @@ public class HibernateItemWriterTests { @Before public void setUp() throws Exception { - writer = new HibernateItemWriter(); - ht = mock(HibernateOperations.class,"ht"); + writer = new HibernateItemWriter<>(); factory = mock(SessionFactory.class); currentSession = mock(Session.class); + + when(this.factory.getCurrentSession()).thenReturn(this.currentSession); } /** @@ -63,14 +60,14 @@ public class HibernateItemWriterTests { */ @Test public void testAfterPropertiesSet() throws Exception { - writer = new HibernateItemWriter(); + writer = new HibernateItemWriter<>(); try { writer.afterPropertiesSet(); fail("Expected IllegalArgumentException"); } catch (IllegalStateException e) { // expected - assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("HibernateOperations") >= 0); + assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("SessionFactory") >= 0); } } @@ -80,22 +77,21 @@ public class HibernateItemWriterTests { * * @throws Exception */ - @SuppressWarnings("deprecation") @Test public void testAfterPropertiesSetWithDelegate() throws Exception { - writer.setHibernateTemplate(ht); + writer.setSessionFactory(this.factory); writer.afterPropertiesSet(); } @SuppressWarnings("deprecation") @Test public void testWriteAndFlushSunnyDayHibernate3() throws Exception { - writer.setHibernateTemplate(ht); - when(ht.contains("foo")).thenReturn(true); - when(ht.contains("bar")).thenReturn(false); - ht.saveOrUpdate("bar"); - ht.flush(); - ht.clear(); + this.writer.setSessionFactory(this.factory); + when(this.currentSession.contains("foo")).thenReturn(true); + when(this.currentSession.contains("bar")).thenReturn(false); + this.currentSession.saveOrUpdate("bar"); + this.currentSession.flush(); + this.currentSession.clear(); List items = Arrays.asList(new String[] { "foo", "bar" }); writer.write(items); @@ -105,9 +101,9 @@ public class HibernateItemWriterTests { @SuppressWarnings("deprecation") @Test public void testWriteAndFlushWithFailureHibernate3() throws Exception { - writer.setHibernateTemplate(ht); + this.writer.setSessionFactory(this.factory); final RuntimeException ex = new RuntimeException("ERROR"); - when(ht.contains("foo")).thenThrow(ex); + when(this.currentSession.contains("foo")).thenThrow(ex); try { writer.write(Collections.singletonList("foo")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java new file mode 100644 index 000000000..595a72e8e --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/HibernateItemWriterBuilderTests.java @@ -0,0 +1,112 @@ +/* + * Copyright 2017 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 + * + * http://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.batch.item.database.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.springframework.batch.item.database.HibernateItemWriter; +import org.springframework.batch.item.sample.Foo; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * @author Michael Minella + */ +public class HibernateItemWriterBuilderTests { + + @Mock + private SessionFactory sessionFactory; + + @Mock + private Session session; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(this.sessionFactory.getCurrentSession()).thenReturn(this.session); + } + + @Test + public void testConfiguration() { + HibernateItemWriter itemWriter = new HibernateItemWriterBuilder() + .sessionFactory(this.sessionFactory) + .build(); + + itemWriter.afterPropertiesSet(); + + List foos = getFoos(); + + itemWriter.write(foos); + + verify(this.session).saveOrUpdate(foos.get(0)); + verify(this.session).saveOrUpdate(foos.get(1)); + verify(this.session).saveOrUpdate(foos.get(2)); + } + + @Test + public void testConfigurationClearSession() { + HibernateItemWriter itemWriter = new HibernateItemWriterBuilder() + .sessionFactory(this.sessionFactory) + .clearSession(false) + .build(); + + itemWriter.afterPropertiesSet(); + + List foos = getFoos(); + + itemWriter.write(foos); + + verify(this.session).saveOrUpdate(foos.get(0)); + verify(this.session).saveOrUpdate(foos.get(1)); + verify(this.session).saveOrUpdate(foos.get(2)); + verify(this.session, never()).clear(); + } + + @Test + public void testValidation() { + try { + new HibernateItemWriterBuilder() + .build(); + } + catch (IllegalStateException ise) { + assertEquals("Incorrect message", "SessionFactory must be provided", ise.getMessage()); + } + } + + private List getFoos() { + List foos = new ArrayList<>(3); + + for(int i = 1; i < 4; i++) { + Foo foo = new Foo(); + foo.setName("foo" + i); + foo.setValue(i); + foos.add(foo); + } + + return foos; + } +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java index e391eb076..0ff93372e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/JdbcBatchItemWriterBuilderTests.java @@ -85,12 +85,6 @@ public class JdbcBatchItemWriterBuilderTests { verifyWrite(); } - private void verifyWrite() { - verifyRow(1, "two", "three"); - verifyRow(4, "five", "six"); - verifyRow(7, "eight", "nine"); - } - @Test public void testCustomJdbcTemplate() throws Exception { NamedParameterJdbcOperations template = new NamedParameterJdbcTemplate(this.dataSource); @@ -235,6 +229,12 @@ public class JdbcBatchItemWriterBuilderTests { } } + private void verifyWrite() { + verifyRow(1, "two", "three"); + verifyRow(4, "five", "six"); + verifyRow(7, "eight", "nine"); + } + private List> buildMapItems() { List> items = new ArrayList<>(3);