diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 67a5c36fed..ba3baf6636 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -55,5 +55,6 @@
spring-hibernate-5
spring-hibernate4
spring-jpa
+ spring-persistence-simple
diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md
index 2f2a27e4ac..24cbb3ee8b 100644
--- a/persistence-modules/spring-jpa/README.md
+++ b/persistence-modules/spring-jpa/README.md
@@ -4,7 +4,6 @@
### Relevant Articles:
-- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
- [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa)
- [JPA Pagination](http://www.baeldung.com/jpa-pagination)
diff --git a/persistence-modules/spring-persistence-simple/.gitignore b/persistence-modules/spring-persistence-simple/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md
new file mode 100644
index 0000000000..2fcd05e84a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/README.md
@@ -0,0 +1,18 @@
+=========
+
+## Spring Persistence Example Project
+
+
+### Relevant Articles:
+- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
+
+
+### Eclipse Config
+After importing the project into Eclipse, you may see the following error:
+"No persistence xml file found in project"
+
+This can be ignored:
+- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project"
+Or:
+- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator
+
diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml
new file mode 100644
index 0000000000..e624af4ea6
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/pom.xml
@@ -0,0 +1,114 @@
+
+ 4.0.0
+ spring-persistence-simple
+ 0.1-SNAPSHOT
+ spring-persistence-simple
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+
+ org.springframework
+ spring-orm
+ ${org.springframework.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
+
+
+
+ org.hibernate
+ hibernate-entitymanager
+ ${hibernate.version}
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector-java.version}
+ runtime
+
+
+ org.springframework.data
+ spring-data-jpa
+ ${spring-data-jpa.version}
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+ test
+
+
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
+
+
+
+ spring-persistence-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ 5.1.6.RELEASE
+
+
+ 5.4.2.Final
+ 6.0.6
+ 2.1.6.RELEASE
+
+
+ 21.0
+ 3.5
+ 3.8.0
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java
new file mode 100644
index 0000000000..ec0d4bca3c
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java
@@ -0,0 +1,87 @@
+package org.baeldung.config;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@PropertySource({ "classpath:persistence-h2.properties" })
+@ComponentScan({ "org.baeldung.persistence" })
+@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
+public class PersistenceJPAConfig {
+
+ @Autowired
+ private Environment env;
+
+ public PersistenceJPAConfig() {
+ super();
+ }
+
+ // beans
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+ em.setDataSource(dataSource());
+ em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
+
+ final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ em.setJpaVendorAdapter(vendorAdapter);
+ em.setJpaProperties(additionalProperties());
+
+ return em;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ final DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(emf);
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ final Properties additionalProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+ hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false");
+
+
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java
new file mode 100644
index 0000000000..13007d9fcc
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java
@@ -0,0 +1,46 @@
+package org.baeldung.persistence.dao;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+public abstract class AbstractJpaDAO {
+
+ private Class clazz;
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ public final void setClazz(final Class clazzToSet) {
+ this.clazz = clazzToSet;
+ }
+
+ public T findOne(final long id) {
+ return entityManager.find(clazz, id);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List findAll() {
+ return entityManager.createQuery("from " + clazz.getName()).getResultList();
+ }
+
+ public void create(final T entity) {
+ entityManager.persist(entity);
+ }
+
+ public T update(final T entity) {
+ return entityManager.merge(entity);
+ }
+
+ public void delete(final T entity) {
+ entityManager.remove(entity);
+ }
+
+ public void deleteById(final long entityId) {
+ final T entity = findOne(entityId);
+ delete(entity);
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java
new file mode 100644
index 0000000000..77978c5cf2
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java
@@ -0,0 +1,17 @@
+package org.baeldung.persistence.dao;
+
+import org.baeldung.persistence.model.Foo;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class FooDao extends AbstractJpaDAO implements IFooDao {
+
+ public FooDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java
new file mode 100644
index 0000000000..f5799522e2
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java
@@ -0,0 +1,21 @@
+package org.baeldung.persistence.dao;
+
+import java.util.List;
+
+import org.baeldung.persistence.model.Foo;
+
+public interface IFooDao {
+
+ Foo findOne(long id);
+
+ List findAll();
+
+ void create(Foo entity);
+
+ Foo update(Foo entity);
+
+ void delete(Foo entity);
+
+ void deleteById(long entityId);
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java
new file mode 100644
index 0000000000..b602e57562
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java
@@ -0,0 +1,102 @@
+package org.baeldung.persistence.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
+
+@Entity
+public class Bar implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ @OneToMany(mappedBy = "bar", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+ @OrderBy("name ASC")
+ List fooList;
+
+ public Bar() {
+ super();
+ }
+
+ public Bar(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public List getFooList() {
+ return fooList;
+ }
+
+ public void setFooList(final List fooList) {
+ this.fooList = fooList;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Bar other = (Bar) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Bar [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java
new file mode 100644
index 0000000000..5294860311
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java
@@ -0,0 +1,92 @@
+package org.baeldung.persistence.model;
+
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
+public class Foo implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "ID")
+ private Long id;
+ @Column(name = "NAME")
+ private String name;
+
+ @ManyToOne(targetEntity = Bar.class, fetch = FetchType.EAGER)
+ @JoinColumn(name = "BAR_ID")
+ private Bar bar;
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(final Bar bar) {
+ this.bar = bar;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java
new file mode 100644
index 0000000000..6d1bb0adbe
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java
@@ -0,0 +1,36 @@
+package org.baeldung.persistence.service;
+
+import java.util.List;
+
+import org.baeldung.persistence.dao.IFooDao;
+import org.baeldung.persistence.model.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@Transactional
+public class FooService {
+
+ @Autowired
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ public void create(final Foo entity) {
+ dao.create(entity);
+ }
+
+ public Foo findOne(final long id) {
+ return dao.findOne(id);
+ }
+
+ public List findAll() {
+ return dao.findAll();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml
new file mode 100644
index 0000000000..ec0dc2469a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties
new file mode 100644
index 0000000000..716a96fde3
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties
@@ -0,0 +1,13 @@
+# jdbc.X
+jdbc.driverClassName=org.h2.Driver
+jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
+jdbc.user=sa
+jdbc.pass=
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+hibernate.show_sql=true
+hibernate.hbm2ddl.auto=create-drop
+hibernate.cache.use_second_level_cache=true
+hibernate.cache.use_query_cache=true
+hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml
new file mode 100644
index 0000000000..6304fa0a65
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..76c34affb9
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java
@@ -0,0 +1,157 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooPaginationPersistenceIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Autowired
+ private FooService fooService;
+
+ @Before
+ public final void before() {
+ final int minimalNumberOfEntities = 25;
+ if (fooService.findAll().size() <= minimalNumberOfEntities) {
+ for (int i = 0; i < minimalNumberOfEntities; i++) {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+ }
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingFirstPage_thenCorrect() {
+ final int pageSize = 10;
+
+ final Query query = entityManager.createQuery("From Foo");
+ configurePagination(query, 1, pageSize);
+
+ // When
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingLastPage_thenCorrect() {
+ final int pageSize = 10;
+ final Query queryTotal = entityManager.createQuery("Select count(f.id) from Foo f");
+ final long countResult = (long) queryTotal.getSingleResult();
+
+ final Query query = entityManager.createQuery("Select f from Foo as f order by f.id");
+ final int lastPage = (int) ((countResult / pageSize) + 1);
+ configurePagination(query, lastPage, pageSize);
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(lessThan(pageSize + 1)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPage_thenCorrect() {
+ final int pageSize = 10;
+
+ final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.name");
+ final List fooIds = queryIds.getResultList();
+
+ final Query query = entityManager.createQuery("Select f from Foo as f where f.id in :ids");
+ query.setParameter("ids", fooIds.subList(0, pageSize));
+
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenCorrect() {
+ final int pageSize = 10;
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ typedQuery.setFirstResult(0);
+ typedQuery.setMaxResults(pageSize);
+ final List fooList = typedQuery.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenNoExceptions() {
+ int pageNumber = 1;
+ final int pageSize = 10;
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+
+ final CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class);
+ countQuery.select(criteriaBuilder.count(countQuery.from(Foo.class)));
+ final Long count = entityManager.createQuery(countQuery).getSingleResult();
+
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+
+ TypedQuery typedQuery;
+ while (pageNumber < count.intValue()) {
+ typedQuery = entityManager.createQuery(select);
+ typedQuery.setFirstResult(pageNumber - 1);
+ typedQuery.setMaxResults(pageSize);
+ System.out.println("Current page: " + typedQuery.getResultList());
+ pageNumber += pageSize;
+ }
+
+ }
+
+ // UTIL
+
+ final int determineLastPage(final int pageSize, final long countResult) {
+ return (int) (countResult / pageSize) + 1;
+ }
+
+ final void configurePagination(final Query query, final int pageNumber, final int pageSize) {
+ query.setFirstResult((pageNumber - 1) * pageSize);
+ query.setMaxResults(pageSize);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..e1b53c8ded
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -0,0 +1,69 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooServicePersistenceIntegrationTest {
+
+ @Autowired
+ private FooService service;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ service.create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenEntityWithLongNameIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ public final void whenSameEntityIsCreatedTwice_thenDataException() {
+ final Foo entity = new Foo(randomAlphabetic(8));
+ service.create(entity);
+ service.create(entity);
+ }
+
+ @Test(expected = DataAccessException.class)
+ public final void temp_whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenFound() {
+ final Foo fooEntity = new Foo("abc");
+ service.create(fooEntity);
+ final Foo found = service.findOne(fooEntity.getId());
+ Assert.assertNotNull(found);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java
new file mode 100644
index 0000000000..40249b4b30
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java
@@ -0,0 +1,118 @@
+package org.baeldung.persistence.service;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+@SuppressWarnings("unchecked")
+public class FooServiceSortingIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ // tests
+
+ @Test
+ public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() {
+ final String jql = "Select f from Foo as f order by f.id";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() {
+ final String jql = "Select f from Foo as f order by f.id desc";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByTwoAttributes_thenPrintSortedResult() {
+ final String jql = "Select f from Foo as f order by f.name asc, f.id desc";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingFooByBar_thenBarsSorted() {
+ final String jql = "Select f from Foo as f order by f.name, f.bar.id";
+ final Query barJoinQuery = entityManager.createQuery(jql);
+ final List fooList = barJoinQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ if (foo.getBar() != null) {
+ System.out.print("-------BarId:" + foo.getBar().getId());
+ }
+ }
+ }
+
+ @Test
+ public final void whenSortinfBar_thenPrintBarsSortedWithFoos() {
+ final String jql = "Select b from Bar as b order by b.id";
+ final Query barQuery = entityManager.createQuery(jql);
+ final List barList = barQuery.getResultList();
+ for (final Bar bar : barList) {
+ System.out.println("Bar Id:" + bar.getId());
+ for (final Foo foo : bar.getFooList()) {
+ System.out.println("FooName:" + foo.getName());
+ }
+ }
+ }
+
+ @Test
+ public final void whenSortingFooWithCriteria_thenPrintSortedFoos() {
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ final List fooList = typedQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() {
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id")));
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ final List fooList = typedQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java
new file mode 100644
index 0000000000..c530003ac1
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java
@@ -0,0 +1,64 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooServiceSortingWitNullsManualIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Autowired
+ private FooService service;
+
+ // tests
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenSortingByStringNullLast_thenLastNull() {
+ service.create(new Foo());
+ service.create(new Foo(randomAlphabetic(6)));
+
+ final String jql = "Select f from Foo as f order by f.name desc NULLS LAST";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenSortingByStringNullFirst_thenFirstNull() {
+ service.create(new Foo());
+
+ final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ }
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file