BATCH-1904: Updated to support Hibernate 4

This commit is contained in:
Michael Minella
2012-12-26 15:05:06 -06:00
parent 1824fff441
commit 6955ab1d6b
17 changed files with 237 additions and 99 deletions

View File

@@ -4,8 +4,8 @@
<artifactId>spring-batch-infrastructure</artifactId>
<packaging>jar</packaging>
<name>Infrastructure</name>
<description><![CDATA[The Spring Batch Infrastructure is a set of
low-level components, interfaces and tools for batch processing
<description><![CDATA[The Spring Batch Infrastructure is a set of
low-level components, interfaces and tools for batch processing
applications and optimisations.]]>
</description>
<url>http://static.springframework.org/spring-batch/${project.artifactId}</url>
@@ -108,7 +108,7 @@
<artifactId>derby</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<!-- <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<optional>true</optional>
@@ -118,7 +118,19 @@
<artifactId>hibernate-entitymanager</artifactId>
<optional>true</optional>
</dependency>
<dependency>
-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.9.Final</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.9.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<optional>true</optional>

View File

@@ -19,11 +19,12 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.context.spi.CurrentSessionContext;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.orm.hibernate3.HibernateOperations;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;
/**
@@ -34,11 +35,21 @@ import org.springframework.util.Assert;
* default (see {@link #setClearSession(boolean) clearSession} property).<br/>
* <br/>
*
<<<<<<< HEAD
* The writer is thread safe after its properties are set (normal singleton
* behavior), so it can be used to write in multiple concurrent transactions.
*
* @author Dave Syer
* @author Thomas Risberg
=======
* The writer is thread safe once properties are set (normal singleton behavior)
* if a {@link CurrentSessionContext} that uses only one session per thread is
* used.
*
* @author Dave Syer
* @author Thomas Risberg
* @author Michael Minella
>>>>>>> BATCH-1904: Updated to support Hibernate 4
*
*/
public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
@@ -47,6 +58,7 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
.getLog(HibernateItemWriter.class);
private HibernateOperations hibernateTemplate;
private SessionFactory sessionFactory;
private boolean clearSession = true;
@@ -66,19 +78,19 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
*
* @param hibernateTemplate
* the hibernateTemplate to set
* @deprecated As of 2.2 in favor of using Hibernate's session management APIs directly
*/
public void setHibernateTemplate(HibernateOperations hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
/**
* Set the Hibernate SessionFactory to be used internally. Will
* automatically create a HibernateTemplate for the given SessionFactory.
* Set the Hibernate SessionFactory to be used internally.
*
* @see #setHibernateTemplate
* @param sessionFactory session factory to be used by the writer
*/
public final void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
this.sessionFactory = sessionFactory;
}
/**
@@ -86,8 +98,8 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
*/
@Override
public void afterPropertiesSet() {
Assert.notNull(hibernateTemplate,
"HibernateItemWriter requires a HibernateOperations");
Assert.state(!(hibernateTemplate == null && sessionFactory == null),
"Either HibernateOperations or SessionFactory must be provided");
}
/**
@@ -98,21 +110,70 @@ public class HibernateItemWriter<T> implements ItemWriter<T>, InitializingBean {
*/
@Override
public final void write(List<? extends T> items) {
doWrite(hibernateTemplate, items);
hibernateTemplate.flush();
if (clearSession) {
hibernateTemplate.clear();
if(sessionFactory == null) {
doWrite(hibernateTemplate, items);
hibernateTemplate.flush();
if (clearSession) {
hibernateTemplate.clear();
}
}
else {
doWrite(sessionFactory, items);
sessionFactory.getCurrentSession().flush();
if(clearSession) {
sessionFactory.getCurrentSession().clear();
}
}
}
/**
* Do perform the actual write operation. This can be overridden in a
* subclass if necessary.
* Do perform the actual write operation using Hibernate's API.
* This can be overridden in a subclass if necessary.
*
* @param hibernateTemplate
* the HibernateTemplate to use for the operation
* @param items
* the list of items to use for the write
* @deprecated As of 2.2 in favor of using Hibernate's session management APIs directly
*/
protected void doWrite(SessionFactory sessionFactory, List<? extends T> items) {
if (logger.isDebugEnabled()) {
logger.debug("Writing to Hibernate with " + items.size()
+ " items.");
}
Session currentSession = sessionFactory.getCurrentSession();
if (!items.isEmpty()) {
long saveOrUpdateCount = 0;
for (T item : items) {
if (!currentSession.contains(item)) {
currentSession.saveOrUpdate(item);
saveOrUpdateCount++;
}
}
if (logger.isDebugEnabled()) {
logger.debug(saveOrUpdateCount + " entities saved/updated.");
logger.debug((items.size() - saveOrUpdateCount)
+ " entities found in session.");
}
}
}
/**
<<<<<<< HEAD
* Do perform the actual write operation. This can be overridden in a
* subclass if necessary.
=======
* Do perform the actual write operation using {@link HibernateOperations}.
* This can be overridden in a subclass if necessary.
>>>>>>> BATCH-1904: Updated to support Hibernate 4
*
* @param hibernateTemplate
* the HibernateTemplate to use for the operation
* @param items
* the list of items to use for the write
* @deprecated As of 2.2 in favor of using Hibernate's session management APIs directly
*/
protected void doWrite(HibernateOperations hibernateTemplate,
List<? extends T> items) {

View File

@@ -6,18 +6,18 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.sample.Foo;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
/**
* Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}.
*
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public abstract class AbstractHibernateCursorItemReaderIntegrationTests extends
AbstractGenericDataSourceItemReaderIntegrationTests {
AbstractGenericDataSourceItemReaderIntegrationTests {
@Override
@Override
protected ItemReader<Foo> createItemReader() throws Exception {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
@@ -26,7 +26,7 @@ public abstract class AbstractHibernateCursorItemReaderIntegrationTests extends
customizeSessionFactory(factoryBean);
factoryBean.afterPropertiesSet();
SessionFactory sessionFactory = (SessionFactory) factoryBean.getObject();
SessionFactory sessionFactory = factoryBean.getObject();
HibernateCursorItemReader<Foo> hibernateReader = new HibernateCursorItemReader<Foo>();
setQuery(hibernateReader);

View File

@@ -1,21 +1,21 @@
package org.springframework.batch.item.database;
import org.hibernate.SessionFactory;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.sample.Foo;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
@RunWith(JUnit4.class)
public class HibernateCursorItemReaderCommonTests extends AbstractDatabaseItemStreamItemReaderTests {
@Override
@Override
protected ItemReader<Foo> getItemReader() throws Exception {
SessionFactory sessionFactory = createSessionFactory();
String hsqlQuery = "from Foo";
@@ -30,18 +30,18 @@ public class HibernateCursorItemReaderCommonTests extends AbstractDatabaseItemSt
return reader;
}
private SessionFactory createSessionFactory() throws Exception {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(getDataSource());
factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("Foo.hbm.xml", getClass()) });
factoryBean.afterPropertiesSet();
return (SessionFactory) factoryBean.getObject();
return factoryBean.getObject();
}
@Override
@Override
protected void pointToEmptyInput(ItemReader<Foo> tested) throws Exception {
HibernateCursorItemReader<Foo> reader = (HibernateCursorItemReader<Foo>) tested;
reader.close();

View File

@@ -7,28 +7,28 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.junit.Test;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.sample.Foo;
/**
* Tests for {@link HibernateCursorItemReader} using standard hibernate {@link Session}.
*
*
* @author Robert Kasanicky
*/
public class HibernateCursorItemReaderStatefulIntegrationTests extends AbstractHibernateCursorItemReaderIntegrationTests {
@Override
@Override
protected boolean isUseStatelessSession() {
return false;
}
//Ensure close is called on the stateful session correctly.
@Test
public void testStatefulClose(){
SessionFactory sessionFactory = createMock(SessionFactory.class);
Session session = createMock(Session.class);
Query scrollableResults = createNiceMock(Query.class);
@@ -36,21 +36,21 @@ public class HibernateCursorItemReaderStatefulIntegrationTests extends AbstractH
itemReader.setSessionFactory(sessionFactory);
itemReader.setQueryString("testQuery");
itemReader.setUseStatelessSession(false);
expect(sessionFactory.openSession()).andReturn(session);
expect(session.createQuery("testQuery")).andReturn(scrollableResults);
expect(scrollableResults.setFetchSize(0)).andReturn(scrollableResults);
expect(session.close()).andReturn(null);
replay(sessionFactory);
replay(session);
replay(scrollableResults);
itemReader.open(new ExecutionContext());
itemReader.close();
verify(sessionFactory);
verify(session);
}
}

View File

@@ -14,13 +14,13 @@ import org.springframework.batch.item.ExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}.
*
*
* @author Robert Kasanicky
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -39,7 +39,7 @@ public class HibernateCursorProjectionItemReaderIntegrationTests {
"Foo.hbm.xml", getClass()) });
factoryBean.afterPropertiesSet();
SessionFactory sessionFactory = (SessionFactory) factoryBean
SessionFactory sessionFactory = factoryBean
.getObject();
reader.setQueryString(hsqlQuery);
@@ -49,7 +49,7 @@ public class HibernateCursorProjectionItemReaderIntegrationTests {
reader.open(new ExecutionContext());
}
@Test
public void testMultipleItemsInProjection() throws Exception {
HibernateCursorItemReader<Object[]> reader = new HibernateCursorItemReader<Object[]>();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2008 the original author or authors.
* Copyright 2006-2013 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.
@@ -15,13 +15,20 @@
*/
package org.springframework.batch.item.database;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.orm.hibernate3.HibernateOperations;
@@ -29,6 +36,7 @@ import org.springframework.orm.hibernate3.HibernateOperations;
/**
* @author Dave Syer
* @author Thomas Risberg
* @author Michael Minella
*/
public class HibernateItemWriterTests {
@@ -36,17 +44,21 @@ public class HibernateItemWriterTests {
HibernateItemWriter<Object> writer;
SessionFactory factory;
Session currentSession;
@Before
public void setUp() throws Exception {
writer = new HibernateItemWriter<Object>();
ht = createMock("ht", HibernateOperations.class);
writer.setHibernateTemplate(ht);
factory = createMock(SessionFactory.class);
currentSession = createMock(Session.class);
}
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateItemWriter#afterPropertiesSet()}
*
*
* @throws Exception
*/
@Test
@@ -56,7 +68,7 @@ public class HibernateItemWriterTests {
writer.afterPropertiesSet();
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
catch (IllegalStateException e) {
// expected
assertTrue("Wrong message for exception: " + e.getMessage(), e.getMessage().indexOf("HibernateOperations") >= 0);
}
@@ -65,38 +77,38 @@ public class HibernateItemWriterTests {
/**
* Test method for
* {@link org.springframework.batch.item.database.HibernateItemWriter#afterPropertiesSet()}
*
*
* @throws Exception
*/
@Test
public void testAfterPropertiesSetWithDelegate() throws Exception {
writer.setHibernateTemplate(ht);
writer.afterPropertiesSet();
}
@Test
public void testWriteAndFlushSunnyDay() throws Exception {
ht.contains("foo");
expectLastCall().andReturn(true);
ht.contains("bar");
expectLastCall().andReturn(false);
public void testWriteAndFlushSunnyDayHibernate3() throws Exception {
writer.setHibernateTemplate(ht);
expect(ht.contains("foo")).andReturn(true);
expect(ht.contains("bar")).andReturn(false);
ht.saveOrUpdate("bar");
ht.flush();
ht.clear();
replay(ht);
List<String> items = Arrays.asList(new String[] { "foo", "bar" });
writer.write(items);
verify(ht);
}
@Test
public void testWriteAndFlushWithFailure() throws Exception {
public void testWriteAndFlushWithFailureHibernate3() throws Exception {
writer.setHibernateTemplate(ht);
final RuntimeException ex = new RuntimeException("ERROR");
ht.contains("foo");
expectLastCall().andThrow(ex);
expect(ht.contains("foo")).andThrow(ex);
replay(ht);
try {
writer.write(Collections.singletonList("foo"));
fail("Expected RuntimeException");
@@ -108,4 +120,42 @@ public class HibernateItemWriterTests {
verify(ht);
}
@Test
public void testWriteAndFlushSunnyDayHibernate4() throws Exception {
writer.setSessionFactory(factory);
expect(factory.getCurrentSession()).andReturn(currentSession).times(3);
expect(currentSession.contains("foo")).andReturn(true);
expect(currentSession.contains("bar")).andReturn(false);
currentSession.saveOrUpdate("bar");
currentSession.flush();
currentSession.clear();
replay(factory, currentSession);
List<String> items = Arrays.asList(new String[] { "foo", "bar" });
writer.write(items);
verify(factory, currentSession);
}
@Test
public void testWriteAndFlushWithFailureHibernate4() throws Exception {
writer.setSessionFactory(factory);
final RuntimeException ex = new RuntimeException("ERROR");
expect(factory.getCurrentSession()).andReturn(currentSession);
expect(currentSession.contains("foo")).andThrow(ex);
replay(factory, currentSession);
try {
writer.write(Collections.singletonList("foo"));
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
assertEquals("ERROR", e.getMessage());
}
verify(factory, currentSession);
}
}

View File

@@ -6,18 +6,18 @@ import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.sample.Foo;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
/**
* Tests for {@link HibernateCursorItemReader} using {@link StatelessSession}.
*
*
* @author Robert Kasanicky
* @author Dave Syer
*/
public class HibernatePagingItemReaderIntegrationTests extends
AbstractGenericDataSourceItemReaderIntegrationTests {
AbstractGenericDataSourceItemReaderIntegrationTests {
@Override
@Override
protected ItemReader<Foo> createItemReader() throws Exception {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
@@ -26,7 +26,7 @@ public class HibernatePagingItemReaderIntegrationTests extends
customizeSessionFactory(factoryBean);
factoryBean.afterPropertiesSet();
SessionFactory sessionFactory = (SessionFactory) factoryBean.getObject();
SessionFactory sessionFactory = factoryBean.getObject();
HibernatePagingItemReader<Foo> hibernateReader = new HibernatePagingItemReader<Foo>();
setQuery(hibernateReader);

View File

@@ -33,7 +33,7 @@ import org.springframework.batch.item.sample.Foo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
@@ -64,13 +64,13 @@ public class HibernateNativeQueryProviderIntegrationTests {
@Before
public void setUp() throws Exception {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMappingLocations(new Resource[] { new ClassPathResource("../Foo.hbm.xml", getClass()) });
factoryBean.afterPropertiesSet();
sessionFactory = (SessionFactory) factoryBean.getObject();
sessionFactory = factoryBean.getObject();
}
@@ -82,7 +82,7 @@ public class HibernateNativeQueryProviderIntegrationTests {
hibernateQueryProvider.setSqlQuery(nativeQuery);
hibernateQueryProvider.afterPropertiesSet();
hibernateQueryProvider.setSession(sessionFactory.getCurrentSession());
hibernateQueryProvider.setSession(sessionFactory.openSession());
Query query = hibernateQueryProvider.createQuery();

View File

@@ -22,8 +22,8 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.classic.Session;
import org.junit.Test;
import org.springframework.batch.item.database.orm.HibernateNativeQueryProvider;
import org.springframework.util.Assert;
@@ -78,7 +78,7 @@ public class HibernateNativeQueryProviderTests {
verify(session, query);
}
private static class Foo {
}

View File

@@ -17,7 +17,7 @@
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="bar"/>
<property name="jpaVendorAdapter">
@@ -27,6 +27,7 @@
</property>
</bean>
<bean id="incrementerParent" class="org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer"
abstract="true">
<property name="dataSource" ref="dataSource" />

View File

@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<tx:annotation-driven/>
<bean class="test.jdbc.datasource.DataSourceInitializer">
<property name="dataSource" ref="dataSource"/>
<property name="initScripts" value="org/springframework/batch/item/database/init-foo-schema-hsqldb.sql" />

View File

@@ -27,6 +27,11 @@
<name>Dave Syer</name>
<email>david.syer@springsource.com</email>
</developer>
<developer>
<id>mminella</id>
<name>Michael Minella</name>
<email>mminella@vmware.com</email>
</developer>
</developers>
<properties>
<spring.framework.version>3.2.0.RELEASE</spring.framework.version>
@@ -422,7 +427,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.3.2.GA</version>
<version>4.1.9.Final</version>
<optional>true</optional>
<exclusions>
<exclusion>
@@ -446,7 +451,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.2.GA</version>
<version>4.1.9.Final</version>
<optional>true</optional>
<exclusions>
<exclusion>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2007 the original author or authors.
* Copyright 2006-2013 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.
@@ -23,33 +23,32 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.CustomerCreditDao;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.orm.hibernate3.HibernateOperations;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.util.Assert;
/**
* Delegates writing to a custom DAO and flushes + clears hibernate session to
* fulfill the {@link ItemWriter} contract.
*
*
* @author Robert Kasanicky
* @author Michael Minella
*/
public class HibernateAwareCustomerCreditItemWriter implements ItemWriter<CustomerCredit>, InitializingBean {
private CustomerCreditDao dao;
private HibernateOperations hibernateTemplate;
private SessionFactory sessionFactory;
public void write(List<? extends CustomerCredit> items) throws Exception {
for (CustomerCredit credit : items) {
dao.writeCredit(credit);
}
try {
hibernateTemplate.flush();
sessionFactory.getCurrentSession().flush();
}
finally {
// this should happen automatically on commit, but to be on the safe
// side...
hibernateTemplate.clear();
sessionFactory.getCurrentSession().clear();
}
}
@@ -59,11 +58,11 @@ public class HibernateAwareCustomerCreditItemWriter implements ItemWriter<Custom
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
this.sessionFactory = sessionFactory;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(hibernateTemplate, "Hibernate session factory must be set");
Assert.state(sessionFactory != null, "Hibernate SessionFactory is required");
Assert.notNull(dao, "Delegate DAO must be set");
}

View File

@@ -18,27 +18,32 @@ package org.springframework.batch.sample.domain.trade.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.RepeatListener;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.sample.domain.trade.CustomerCredit;
import org.springframework.batch.sample.domain.trade.CustomerCreditDao;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
* @author Lucas Ward
* @author Dave Syer
*
*
*/
public class HibernateCreditDao extends HibernateDaoSupport implements
public class HibernateCreditDao implements
CustomerCreditDao, RepeatListener {
private int failOnFlush = -1;
private List<Throwable> errors = new ArrayList<Throwable>();
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Public accessor for the errors property.
*
*
* @return the errors - a list of Throwable instances
*/
public List<Throwable> getErrors() {
@@ -47,7 +52,7 @@ public class HibernateCreditDao extends HibernateDaoSupport implements
/*
* (non-Javadoc)
*
*
* @see org.springframework.batch.sample.domain.trade.internal.CustomerCreditWriter#write(org.springframework.batch.sample.domain.CustomerCredit)
*/
public void writeCredit(CustomerCredit customerCredit) {
@@ -57,15 +62,15 @@ public class HibernateCreditDao extends HibernateDaoSupport implements
newCredit.setId(customerCredit.getId());
newCredit.setName(customerCredit.getName());
newCredit.setCredit(customerCredit.getCredit());
getHibernateTemplate().save(newCredit);
sessionFactory.getCurrentSession().save(newCredit);
} else {
getHibernateTemplate().update(customerCredit);
sessionFactory.getCurrentSession().update(customerCredit);
}
}
/*
* (non-Javadoc)
*
*
* @see org.springframework.batch.io.OutputSource#write(java.lang.Object)
*/
public void write(Object output) {
@@ -74,7 +79,7 @@ public class HibernateCreditDao extends HibernateDaoSupport implements
/**
* Public setter for the failOnFlush property.
*
*
* @param failOnFlush
* the ID of the record you want to fail on flush (for testing)
*/

View File

@@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingLocations" value="classpath*:/org/springframework/batch/sample/domain/**/*.hbm.xml" />
<property name="hibernateProperties">
@@ -16,7 +16,7 @@
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" lazy-init="true">
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" lazy-init="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

View File

@@ -158,6 +158,7 @@ public class HibernateFailureJobFunctionalTests {
public void processRow(ResultSet rs) throws SQLException {
final BigDecimal creditBeforeUpdate = creditsBeforeUpdate.get(i++);
final BigDecimal expectedCredit = creditBeforeUpdate.add(CREDIT_INCREASE);
System.out.println("expectedCredit = " + expectedCredit + " db credit = " + rs.getBigDecimal(CREDIT_COLUMN));
if (expectedCredit.equals(rs.getBigDecimal(CREDIT_COLUMN))) {
matches.add(rs.getBigDecimal(ID_COLUMN));
}