diff --git a/src/main/java/org/springframework/data/jpa/repository/JpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/JpaRepository.java index cc4726151..8bfd19b4f 100644 --- a/src/main/java/org/springframework/data/jpa/repository/JpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/JpaRepository.java @@ -18,6 +18,8 @@ package org.springframework.data.jpa.repository; import java.io.Serializable; import java.util.List; +import javax.persistence.EntityManager; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; @@ -75,4 +77,14 @@ public interface JpaRepository extends * @return the saved entity */ T saveAndFlush(T entity); + + + /** + * Deletes the given entities in a batch which means it will create a single + * {@link Query}. Assume that we will clear the {@link EntityManager} after + * the call. + * + * @param entities + */ + void deleteInBatch(Iterable entities); } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index a3a83774f..50f633658 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -34,7 +34,6 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.query.QueryUtils; import org.springframework.data.repository.Repository; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @@ -58,6 +57,13 @@ public class SimpleJpaRepository extends private final PersistenceProvider provider; + /** + * Creates a new {@link SimpleJpaRepository} to manage objects of the given + * domain type. + * + * @param domainClass + * @param entityManager + */ public SimpleJpaRepository(Class domainClass, EntityManager entityManager) { super(domainClass); @@ -87,16 +93,16 @@ public class SimpleJpaRepository extends /** * Factory method to create {@link SimpleJpaRepository} instances. * - * @param the type of the entity to handle - * @param the type of the entity's identifier - * @param entityManager the {@link EntityManager} backing the repository * @param domainClass the domain class to handle + * @param entityManager the {@link EntityManager} backing the repository + * @param the type of the entity to handle + * @param the type of the entity's identifier * @return */ - public static Repository create( - final EntityManager entityManager, final Class domainClass) { + public static Repository create( + Class domainClass, EntityManager entityManager) { - return new SimpleJpaRepository(domainClass, entityManager); + return new SimpleJpaRepository(domainClass, entityManager); } @@ -106,7 +112,7 @@ public class SimpleJpaRepository extends * @see * org.springframework.data.repository.Repository#delete(java.lang.Object) */ - public void delete(final T entity) { + public void delete(T entity) { em.remove(em.contains(entity) ? entity : em.merge(entity)); } @@ -118,7 +124,26 @@ public class SimpleJpaRepository extends * @see * org.springframework.data.repository.Repository#delete(java.lang.Iterable) */ - public void delete(final Iterable entities) { + public void delete(Iterable entities) { + + if (entities == null) { + return; + } + + for (T entity : entities) { + delete(entity); + } + } + + + /* + * (non-Javadoc) + * + * @see + * org.springframework.data.jpa.repository.JpaRepository#deleteInBatch(java + * .lang.Iterable) + */ + public void deleteInBatch(Iterable entities) { if (null == entities || !entities.iterator().hasNext()) { return; @@ -126,6 +151,7 @@ public class SimpleJpaRepository extends applyAndBind(getQueryString(DELETE_ALL_QUERY_STRING, getDomainClass()), entities, em).executeUpdate(); + em.clear(); } @@ -137,6 +163,7 @@ public class SimpleJpaRepository extends public void deleteAll() { em.createQuery(getDeleteAllQueryString()).executeUpdate(); + em.clear(); } @@ -148,11 +175,10 @@ public class SimpleJpaRepository extends * ) */ @Transactional(readOnly = true) - public T findById(final ID primaryKey) { + public T findById(ID id) { - Assert.notNull(primaryKey, "The given primaryKey must not be null!"); - - return em.find(getDomainClass(), primaryKey); + Assert.notNull(id, "The given id must not be null!"); + return em.find(getDomainClass(), id); } @@ -164,11 +190,10 @@ public class SimpleJpaRepository extends * ) */ @Transactional(readOnly = true) - public boolean exists(final ID primaryKey) { + public boolean exists(ID id) { - Assert.notNull(primaryKey, "The given primary key must not be null!"); - - return null != findById(primaryKey); + Assert.notNull(id, "The given id must not be null!"); + return null != findById(id); } @@ -192,7 +217,7 @@ public class SimpleJpaRepository extends * .data.domain.Sort) */ @Transactional(readOnly = true) - public List findAll(final Sort sort) { + public List findAll(Sort sort) { return getQuery(null, sort).getResultList(); } @@ -205,7 +230,7 @@ public class SimpleJpaRepository extends * springframework.data.domain.Pageable) */ @Transactional(readOnly = true) - public Page findAll(final Pageable pageable) { + public Page findAll(Pageable pageable) { if (null == pageable) { return new PageImpl(findAll()); @@ -280,7 +305,7 @@ public class SimpleJpaRepository extends * @see * org.springframework.data.repository.Repository#save(java.lang.Object) */ - public T save(final T entity) { + public T save(T entity) { if (getIsNewStrategy().isNew(entity)) { em.persist(entity); @@ -298,7 +323,7 @@ public class SimpleJpaRepository extends * org.springframework.data.jpa.repository.JpaRepository#saveAndFlush(java * .lang.Object) */ - public T saveAndFlush(final T entity) { + public T saveAndFlush(T entity) { T result = save(entity); flush(); @@ -340,30 +365,14 @@ public class SimpleJpaRepository extends } - /** - * Reads a page of entities for the given JPQL query. - * - * @param pageable - * @param query - * @return a page of entities for the given JPQL query - */ - protected Page readPage(final Pageable pageable, final String query) { - - String queryString = QueryUtils.applySorting(query, pageable.getSort()); - TypedQuery jpaQuery = em.createQuery(queryString, getDomainClass()); - - return readPage(jpaQuery, pageable, null); - } - - /** * @param query * @param spec * @param pageable * @return */ - private Page readPage(final TypedQuery query, - final Pageable pageable, final Specification spec) { + private Page readPage(TypedQuery query, Pageable pageable, + Specification spec) { query.setFirstResult(pageable.getOffset()); query.setMaxResults(pageable.getPageSize()); diff --git a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java index fa2f9bd51..915d0e28f 100644 --- a/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/UserRepositoryTests.java @@ -225,6 +225,18 @@ public class UserRepositoryTests { } + @Test + public void batchDeleteColletionOfEntities() { + + flushTestUsers(); + + long before = repository.count(); + + repository.deleteInBatch(Arrays.asList(firstUser, secondUser)); + assertThat(repository.count(), is(before - 2)); + } + + @Test public void deleteEmptyCollectionDoesNotDeleteAnything() {