class JpaItemWriter<T> implements ItemWriter<T>, InitializingBean {

	protected static final Log logger = LogFactory.getLog(JpaItemWriter.class);

	private EntityManagerFactory entityManagerFactory;

	private boolean usePersist = false;

	private boolean clearPersistenceContext = true;

	/**
	 * Set the EntityManager to be used internally.
	 * @param entityManagerFactory the entityManagerFactory to set
	 */
	public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
		this.entityManagerFactory = entityManagerFactory;
	}

	/**
	 * Set whether the EntityManager should perform a persist instead of a merge.
	 * @param usePersist whether to use persist instead of merge.
	 */
	public void setUsePersist(boolean usePersist) {
		this.usePersist = usePersist;
	}

	/**
	 * Flag to indicate that the persistence context should be cleared and flushed at the
	 * end of the write (default true).
	 * @param clearPersistenceContext the flag value to set
	 * @since 5.1
	 */
	public void setClearPersistenceContext(boolean clearPersistenceContext) {
		this.clearPersistenceContext = clearPersistenceContext;
	}

	/**
	 * Check mandatory properties - there must be an entityManagerFactory.
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.state(entityManagerFactory != null, "An EntityManagerFactory is required");
	}

	/**
	 * Merge all provided items that aren't already in the persistence context and then
	 * flush the entity manager.
	 *
	 * @see org.springframework.batch.item.ItemWriter#write(Chunk)
	 */
	@Override
	public void write(Chunk<? extends T> items) {
		EntityManager entityManager = EntityManagerFactoryUtils.getTransactionalEntityManager(entityManagerFactory);
		if (entityManager == null) {
			throw new DataAccessResourceFailureException("Unable to obtain a transactional EntityManager");
		}
		doWrite(entityManager, items);
		entityManager.flush();
		if (this.clearPersistenceContext) {
			entityManager.clear();
		}
	}

	/**
	 * Do perform the actual write operation. This can be overridden in a subclass if
	 * necessary.
	 * @param entityManager the EntityManager to use for the operation
	 * @param items the list of items to use for the write
	 */
	protected void doWrite(EntityManager entityManager, Chunk<? extends T> items) {<FILL_FUNCTION_BODY>}

}


		if (logger.isDebugEnabled()) {
			logger.debug("Writing to JPA with " + items.size() + " items.");
		}

		if (!items.isEmpty()) {
			long addedToContextCount = 0;
			for (T item : items) {
				if (!entityManager.contains(item)) {
					if (usePersist) {
						entityManager.persist(item);
					}
					else {
						entityManager.merge(item);
					}
					addedToContextCount++;
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug(addedToContextCount + " entities " + (usePersist ? " persisted." : "merged."));
				logger.debug((items.size() - addedToContextCount) + " entities found in persistence context.");
			}
		}

	
<no_super_class>