Skip to content

Commit

Permalink
The findAll method from the JpaRepository is an Anti-Pattern and the …
Browse files Browse the repository at this point in the history
…HibernateRepository should deprecate it #483
  • Loading branch information
vladmihalcea committed Sep 10, 2022
1 parent 10c1e7d commit 8a64d17
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 30 deletions.
Expand Up @@ -14,7 +14,12 @@
*/
public interface HibernateRepository<T> {

//Save methods will trigger an UnsupportedOperationException
//The findAll method will trigger an UnsupportedOperationException

@Deprecated
List<T> findAll();

//The save methods will trigger an UnsupportedOperationException

@Deprecated
<S extends T> S save(S entity);
Expand All @@ -28,7 +33,7 @@ public interface HibernateRepository<T> {
@Deprecated
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

//Persist methods are meant to save newly created entities
//The persist methods are meant to save newly created entities

<S extends T> S persist(S entity);

Expand All @@ -38,7 +43,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> peristAllAndFlush(Iterable<S> entities);

//Merge methods are meant to propagate detached entity state changes
//The merge methods are meant to propagate detached entity state changes
//if they are really needed

<S extends T> S merge(S entity);
Expand All @@ -49,7 +54,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> mergeAllAndFlush(Iterable<S> entities);

//Update methods are meant to force the detached entity state changes
//The update methods are meant to force the detached entity state changes

<S extends T> S update(S entity);

Expand Down
Expand Up @@ -19,24 +19,29 @@ public class HibernateRepositoryImpl<T> implements HibernateRepository<T> {
@PersistenceContext
private EntityManager entityManager;

@Override
public List<T> findAll() {
throw new UnsupportedOperationException("Fetching all records from a given database table is a terrible idea!");
}

@Override
public <S extends T> S save(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> S saveAndFlush(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

public <S extends T> S persist(S entity) {
Expand Down Expand Up @@ -161,7 +166,7 @@ protected Session session() {
return entityManager.unwrap(Session.class);
}

protected <S extends T> S unsupported() {
protected <S extends T> S unsupportedSave() {
throw new UnsupportedOperationException("There's no such thing as a save method in JPA, so don't use this hack!");
}
}
Expand Up @@ -8,6 +8,6 @@
* @author Vlad Mihalcea
*/
@Repository
public interface PostRepository extends JpaRepository<Post, Long>, HibernateRepository<Post> {
public interface PostRepository extends HibernateRepository<Post>, JpaRepository<Post, Long> {

}
Expand Up @@ -105,5 +105,19 @@ public void testSave() {
LOGGER.warn("You shouldn't call the JpaRepository save method!");
}
}

@Test
public void testFindAll() {
try {
transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
postRepository.findAll();
return null;
});

fail("Should throw UnsupportedOperationException!");
} catch (UnsupportedOperationException expected) {
LOGGER.warn("You shouldn't call the JpaRepository findAll method!");
}
}
}

Expand Up @@ -14,7 +14,12 @@
*/
public interface HibernateRepository<T> {

//Save methods will trigger an UnsupportedOperationException
//The findAll method will trigger an UnsupportedOperationException

@Deprecated
List<T> findAll();

//The save methods will trigger an UnsupportedOperationException

@Deprecated
<S extends T> S save(S entity);
Expand All @@ -28,7 +33,7 @@ public interface HibernateRepository<T> {
@Deprecated
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

//Persist methods are meant to save newly created entities
//The persist methods are meant to save newly created entities

<S extends T> S persist(S entity);

Expand All @@ -38,7 +43,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> peristAllAndFlush(Iterable<S> entities);

//Merge methods are meant to propagate detached entity state changes
//The merge methods are meant to propagate detached entity state changes
//if they are really needed

<S extends T> S merge(S entity);
Expand All @@ -49,7 +54,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> mergeAllAndFlush(Iterable<S> entities);

//Update methods are meant to force the detached entity state changes
//The update methods are meant to force the detached entity state changes

<S extends T> S update(S entity);

Expand Down
Expand Up @@ -19,24 +19,29 @@ public class HibernateRepositoryImpl<T> implements HibernateRepository<T> {
@PersistenceContext
private EntityManager entityManager;

@Override
public List<T> findAll() {
throw new UnsupportedOperationException("Fetching all records from a given database table is a terrible idea!");
}

@Override
public <S extends T> S save(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> S saveAndFlush(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

public <S extends T> S persist(S entity) {
Expand Down Expand Up @@ -161,7 +166,7 @@ protected Session session() {
return entityManager.unwrap(Session.class);
}

protected <S extends T> S unsupported() {
protected <S extends T> S unsupportedSave() {
throw new UnsupportedOperationException("There's no such thing as a save method in JPA, so don't use this hack!");
}
}
Expand Up @@ -8,6 +8,6 @@
* @author Vlad Mihalcea
*/
@Repository
public interface PostRepository extends JpaRepository<Post, Long>, HibernateRepository<Post> {
public interface PostRepository extends HibernateRepository<Post>, JpaRepository<Post, Long> {

}
Expand Up @@ -106,5 +106,19 @@ public void testSave() {
LOGGER.warn("You shouldn't call the JpaRepository save method!");
}
}

@Test
public void testFindAll() {
try {
transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
postRepository.findAll();
return null;
});

fail("Should throw UnsupportedOperationException!");
} catch (UnsupportedOperationException expected) {
LOGGER.warn("You shouldn't call the JpaRepository findAll method!");
}
}
}

Expand Up @@ -3,11 +3,23 @@
import java.util.List;

/**
* The {@code HibernateRepository} fixes the problems that the default Spring Data {@code JpaRepository}
* suffers from.
*
* For more details about how to use it, check out <a href=
* "https://vladmihalcea.com/best-spring-data-jparepository/">this article</a>.
*
* @author Vlad Mihalcea
* @version 2.17.0
*/
public interface HibernateRepository<T> {

//Save methods will trigger an UnsupportedOperationException
//The findAll method will trigger an UnsupportedOperationException

@Deprecated
List<T> findAll();

//The save methods will trigger an UnsupportedOperationException

@Deprecated
<S extends T> S save(S entity);
Expand All @@ -21,7 +33,7 @@ public interface HibernateRepository<T> {
@Deprecated
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

//Persist methods are meant to save newly created entities
//The persist methods are meant to save newly created entities

<S extends T> S persist(S entity);

Expand All @@ -31,7 +43,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> peristAllAndFlush(Iterable<S> entities);

//Merge methods are meant to propagate detached entity state changes
//The merge methods are meant to propagate detached entity state changes
//if they are really needed

<S extends T> S merge(S entity);
Expand All @@ -42,7 +54,7 @@ public interface HibernateRepository<T> {

<S extends T> List<S> mergeAllAndFlush(Iterable<S> entities);

//Update methods are meant to force the detached entity state changes
//The update methods are meant to force the detached entity state changes

<S extends T> S update(S entity);

Expand Down
Expand Up @@ -19,24 +19,29 @@ public class HibernateRepositoryImpl<T> implements HibernateRepository<T> {
@PersistenceContext
private EntityManager entityManager;

@Override
public List<T> findAll() {
throw new UnsupportedOperationException("Fetching all records from a given database table is a terrible idea!");
}

@Override
public <S extends T> S save(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAll(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> S saveAndFlush(S entity) {
return unsupported();
return unsupportedSave();
}

@Override
public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
return unsupported();
return unsupportedSave();
}

public <S extends T> S persist(S entity) {
Expand Down Expand Up @@ -161,7 +166,7 @@ protected Session session() {
return entityManager.unwrap(Session.class);
}

protected <S extends T> S unsupported() {
protected <S extends T> S unsupportedSave() {
throw new UnsupportedOperationException("There's no such thing as a save method in JPA, so don't use this hack!");
}
}
Expand Up @@ -8,6 +8,6 @@
* @author Vlad Mihalcea
*/
@Repository
public interface PostRepository extends JpaRepository<Post, Long>, HibernateRepository<Post> {
public interface PostRepository extends HibernateRepository<Post>, JpaRepository<Post, Long> {

}
Expand Up @@ -105,5 +105,19 @@ public void testSave() {
LOGGER.warn("You shouldn't call the JpaRepository save method!");
}
}

@Test
public void testFindAll() {
try {
transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> {
postRepository.findAll();
return null;
});

fail("Should throw UnsupportedOperationException!");
} catch (UnsupportedOperationException expected) {
LOGGER.warn("You shouldn't call the JpaRepository findAll method!");
}
}
}

0 comments on commit 8a64d17

Please sign in to comment.