diff --git a/persistence-modules/spring-data-jpa-crud/README.md b/persistence-modules/spring-data-jpa-crud/README.md
new file mode 100644
index 0000000000..145153b953
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/README.md
@@ -0,0 +1,22 @@
+## Spring Data JPA - CRUD
+
+This module contains articles about CRUD operations in Spring Data JPA
+
+### Relevant Articles:
+- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby)
+- [Spring Data JPA Delete and Relationships](https://www.baeldung.com/spring-data-jpa-delete)
+- [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert)
+- [Spring Data JPA Batch Inserts](https://www.baeldung.com/spring-data-jpa-batch-inserts)
+- [Batch Insert/Update with Hibernate/JPA](https://www.baeldung.com/jpa-hibernate-batch-insert-update)
+- [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush)
+- [How to Implement a Soft Delete with Spring JPA](https://www.baeldung.com/spring-jpa-soft-delete)
+- More articles: [[next-->]](/persistence-modules/spring-data-jpa-crud-2)
+
+### 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-data-jpa-crud/pom.xml b/persistence-modules/spring-data-jpa-crud/pom.xml
new file mode 100644
index 0000000000..0889cfca2a
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/pom.xml
@@ -0,0 +1,64 @@
+
+
+ 4.0.0
+ spring-data-jpa-crud
+ spring-data-jpa-crud
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ com.h2database
+ h2
+
+
+ net.ttddyy
+ datasource-proxy
+ ${datasource-proxy.version}
+
+
+ org.postgresql
+ postgresql
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+ org.testcontainers
+ postgresql
+ ${testcontainers.version}
+ test
+
+
+
+
+
+ 1.4.1
+ 1.12.2
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/Application.java
new file mode 100644
index 0000000000..ce10072031
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/Application.java
@@ -0,0 +1,14 @@
+package com.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableJpaRepositories
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/Application.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/Application.java
new file mode 100644
index 0000000000..aaca760499
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/Application.java
@@ -0,0 +1,17 @@
+package com.baeldung.boot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableJpaRepositories("com.baeldung")
+@EntityScan("com.baeldung")
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/daos/CustomerRepository.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/daos/CustomerRepository.java
new file mode 100644
index 0000000000..7cb7e45b27
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/daos/CustomerRepository.java
@@ -0,0 +1,19 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.boot.domain.Customer;
+
+/**
+ * JPA CrudRepository interface
+ *
+ * @author ysharma2512
+ *
+ */
+@Repository
+@Transactional
+public interface CustomerRepository extends CrudRepository{
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java
new file mode 100644
index 0000000000..e13afd9b45
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/boot/web/controllers/CustomerController.java
@@ -0,0 +1,41 @@
+package com.baeldung.boot.web.controllers;
+
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.boot.daos.CustomerRepository;
+import com.baeldung.boot.domain.Customer;
+
+/**
+ * A simple controller to test the JPA CrudRepository operations
+ * controllers
+ *
+ * @author ysharma2512
+ *
+ */
+@RestController
+public class CustomerController {
+
+ CustomerRepository customerRepository;
+
+ public CustomerController(CustomerRepository customerRepository2) {
+ this.customerRepository = customerRepository2;
+ }
+
+ @PostMapping("/customers")
+ public ResponseEntity> insertCustomers() throws URISyntaxException {
+ Customer c1 = new Customer("James", "Gosling");
+ Customer c2 = new Customer("Doug", "Lea");
+ Customer c3 = new Customer("Martin", "Fowler");
+ Customer c4 = new Customer("Brian", "Goetz");
+ List customers = Arrays.asList(c1, c2, c3, c4);
+ customerRepository.saveAll(customers);
+ return ResponseEntity.ok(customers);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/entity/Employee.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/entity/Employee.java
new file mode 100644
index 0000000000..4c3dbd25b7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/entity/Employee.java
@@ -0,0 +1,36 @@
+package com.baeldung.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Employee {
+
+ @Id
+ private Long id;
+ private String name;
+
+ public Employee() {
+ }
+
+ public Employee(Long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/EmployeeRepository.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/EmployeeRepository.java
new file mode 100644
index 0000000000..8f0a80814b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/EmployeeRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import com.baeldung.entity.Employee;
+
+public interface EmployeeRepository extends JpaRepository {
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/FruitRepository.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/FruitRepository.java
new file mode 100644
index 0000000000..f98d756c13
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/FruitRepository.java
@@ -0,0 +1,27 @@
+package com.baeldung.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.entity.Fruit;
+
+@Repository
+public interface FruitRepository extends JpaRepository {
+
+ Long deleteByName(String name);
+
+ List deleteByColor(String color);
+
+ Long removeByName(String name);
+
+ List removeByColor(String color);
+
+ @Modifying
+ @Query("delete from Fruit f where f.name=:name or f.color=:color")
+ int deleteFruits(@Param("name") String name, @Param("color") String color);
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/Product.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/Product.java
new file mode 100644
index 0000000000..ef06f77c45
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/Product.java
@@ -0,0 +1,68 @@
+package com.baeldung.softdelete;
+
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.Filter;
+import org.hibernate.annotations.FilterDef;
+import org.hibernate.annotations.ParamDef;
+import org.hibernate.annotations.SQLDelete;
+
+@Entity
+@Table(name = "tbl_products")
+@SQLDelete(sql = "UPDATE tbl_products SET deleted = true WHERE id=?")
+@FilterDef(name = "deletedProductFilter", parameters = @ParamDef(name = "isDeleted", type = "boolean"))
+@Filter(name = "deletedProductFilter", condition = "deleted = :isDeleted")
+public class Product implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+
+ private double price;
+
+ private boolean deleted = Boolean.FALSE;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ }
+
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(boolean deleted) {
+ this.deleted = deleted;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductController.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductController.java
new file mode 100644
index 0000000000..ebfdfbb2e7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductController.java
@@ -0,0 +1,34 @@
+package com.baeldung.softdelete;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/api/products")
+public class ProductController {
+
+ @Autowired
+ private ProductService productService;
+
+ @PostMapping
+ public Product createOne(@RequestBody Product product) {
+ return productService.create(product);
+ }
+
+ @DeleteMapping("/{id}")
+ public void removeOne(@PathVariable("id") Long id) {
+ productService.remove(id);
+ }
+
+ @GetMapping
+ public Iterable findAll(@RequestParam(value = "isDeleted", required = false, defaultValue = "false") boolean isDeleted) {
+ return productService.findAll(isDeleted);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductRepository.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductRepository.java
new file mode 100644
index 0000000000..a305a142aa
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductRepository.java
@@ -0,0 +1,7 @@
+package com.baeldung.softdelete;
+
+import org.springframework.data.repository.CrudRepository;
+
+public interface ProductRepository extends CrudRepository{
+
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductService.java b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductService.java
new file mode 100644
index 0000000000..82d02fa87c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/softdelete/ProductService.java
@@ -0,0 +1,35 @@
+package com.baeldung.softdelete;
+
+import javax.persistence.EntityManager;
+
+import org.hibernate.Filter;
+import org.hibernate.Session;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ProductService {
+
+ @Autowired
+ private ProductRepository productRepository;
+
+ @Autowired
+ private EntityManager entityManager;
+
+ public Product create(Product product) {
+ return productRepository.save(product);
+ }
+
+ public void remove(Long id){
+ productRepository.deleteById(id);
+ }
+
+ public Iterable findAll(boolean isDeleted){
+ Session session = entityManager.unwrap(Session.class);
+ Filter filter = session.enableFilter("deletedProductFilter");
+ filter.setParameter("isDeleted", isDeleted);
+ Iterable products = productRepository.findAll();
+ session.disableFilter("deletedProductFilter");
+ return products;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties
new file mode 100644
index 0000000000..d7fb13da08
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+spring.jpa.properties.hibernate.jdbc.batch_size=4
+spring.jpa.properties.hibernate.order_inserts=true
+spring.jpa.properties.hibernate.order_updates=true
+
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringContextTest.java
new file mode 100644
index 0000000000..eaccf4acba
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringContextTest.java
@@ -0,0 +1,17 @@
+package com.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class SpringContextTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java
new file mode 100644
index 0000000000..27c71c5bcc
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/SpringJpaContextIntegrationTest.java
@@ -0,0 +1,19 @@
+package com.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest
+@ContextConfiguration(classes = Application.class)
+public class SpringJpaContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..0fc9918701
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/java/com/baeldung/repository/EmployeeRepositoryIntegrationTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.repository;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.Application;
+import com.baeldung.entity.Employee;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class EmployeeRepositoryIntegrationTest {
+
+ private static final Employee EMPLOYEE1 = new Employee(1L, "John");
+ private static final Employee EMPLOYEE2 = new Employee(2L, "Alice");
+
+ @Autowired
+ private EmployeeRepository employeeRepository;
+
+ @Test
+ public void givenEmployeeEntity_whenInsertWithSave_ThenEmployeeIsPersisted() {
+ employeeRepository.save(EMPLOYEE1);
+ assertEmployeePersisted(EMPLOYEE1);
+ }
+
+ @Test
+ public void givenEmployeeEntity_whenInsertWithSaveAndFlush_ThenEmployeeIsPersisted() {
+ employeeRepository.saveAndFlush(EMPLOYEE2);
+ assertEmployeePersisted(EMPLOYEE2);
+ }
+
+ private void assertEmployeePersisted(Employee input) {
+ Employee employee = employeeRepository.getOne(input.getId());
+ assertThat(employee).isNotNull();
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/resources/application-batchinserts.properties b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-batchinserts.properties
new file mode 100644
index 0000000000..bc9c9a832c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-batchinserts.properties
@@ -0,0 +1,8 @@
+spring.jpa.show-sql=false
+
+spring.jpa.properties.hibernate.jdbc.batch_size=5
+spring.jpa.properties.hibernate.order_inserts=true
+spring.jpa.properties.hibernate.order_updates=true
+spring.jpa.properties.hibernate.batch_versioned_data=true
+
+spring.jpa.properties.hibernate.generate_statistics=true
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/resources/application-stats.properties b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-stats.properties
new file mode 100644
index 0000000000..97bc170ca0
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-stats.properties
@@ -0,0 +1,5 @@
+spring.jpa.properties.hibernate.jdbc.batch_size=4
+spring.jpa.properties.hibernate.order_inserts=true
+spring.jpa.properties.hibernate.order_updates=true
+
+spring.jpa.properties.hibernate.generate_statistics=true
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/resources/application-test.properties b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-test.properties
new file mode 100644
index 0000000000..f9497c8f37
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/resources/application-test.properties
@@ -0,0 +1,2 @@
+spring.jpa.hibernate.ddl-auto=update
+spring.datasource.url=jdbc:h2:mem:jpa3
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-crud/src/test/resources/test-fruit-data.sql b/persistence-modules/spring-data-jpa-crud/src/test/resources/test-fruit-data.sql
new file mode 100644
index 0000000000..d99f42e5a7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-crud/src/test/resources/test-fruit-data.sql
@@ -0,0 +1,6 @@
+truncate table fruit;
+
+insert into fruit(id,name,color) values (1,'apple','red');
+insert into fruit(id,name,color) values (2,'custard apple','green');
+insert into fruit(id,name,color) values (3,'mango','yellow');
+insert into fruit(id,name,color) values (4,'guava','green');
\ No newline at end of file
diff --git a/persistence-modules/spring-data-mongodb/src/live-test/resources/Dockerfile b/persistence-modules/spring-data-mongodb/src/live-test/resources/Dockerfile
new file mode 100644
index 0000000000..9e3634feb0
--- /dev/null
+++ b/persistence-modules/spring-data-mongodb/src/live-test/resources/Dockerfile
@@ -0,0 +1,8 @@
+FROM mongo:4.2.1
+
+COPY init-session.js /docker-entrypoint-initdb.d/
+
+EXPOSE 27017
+
+HEALTHCHECK --interval=5s --timeout=3s --start-period=10s CMD mongo db.stats()
+CMD ["mongod", "--replSet", "rs0"]
diff --git a/persistence-modules/spring-data-mongodb/src/live-test/resources/init-session.js b/persistence-modules/spring-data-mongodb/src/live-test/resources/init-session.js
new file mode 100644
index 0000000000..2e968884cc
--- /dev/null
+++ b/persistence-modules/spring-data-mongodb/src/live-test/resources/init-session.js
@@ -0,0 +1 @@
+rs.initiate();
diff --git a/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-setup.sh b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-setup.sh
new file mode 100644
index 0000000000..78968d51aa
--- /dev/null
+++ b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-setup.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+docker image build -t spring-data-mongodb:live-test .
+
+docker run -p 27017:27017 --name spring-data-mongodb-live-test spring-data-mongodb:live-test
diff --git a/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-teardown.sh b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-teardown.sh
new file mode 100644
index 0000000000..a29163bc7a
--- /dev/null
+++ b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test-teardown.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+docker stop spring-data-mongodb-live-test
+docker rm spring-data-mongodb-live-test
diff --git a/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test.sh b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test.sh
new file mode 100644
index 0000000000..307a68a3bd
--- /dev/null
+++ b/persistence-modules/spring-data-mongodb/src/live-test/resources/live-test.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+mvn clean compile test -P live-all -f ../../../pom.xml
diff --git a/persistence-modules/spring-data-redis/.classpath b/persistence-modules/spring-data-redis/.classpath
new file mode 100644
index 0000000000..8c45832050
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.classpath
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/persistence-modules/spring-data-redis/.factorypath b/persistence-modules/spring-data-redis/.factorypath
new file mode 100644
index 0000000000..62ec6e17b9
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.factorypath
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/persistence-modules/spring-data-redis/.project b/persistence-modules/spring-data-redis/.project
new file mode 100644
index 0000000000..0dc609be2b
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.project
@@ -0,0 +1,28 @@
+
+
+ spring-data-redis
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+ org.springframework.ide.eclipse.boot.validation.springbootbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/persistence-modules/spring-data-redis/.settings/org.eclipse.core.resources.prefs b/persistence-modules/spring-data-redis/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000..839d647eef
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding/=UTF-8
diff --git a/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.apt.core.prefs b/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 0000000000..dfa4f3adb2
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations
+org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations
diff --git a/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.core.prefs b/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..3ad7e6e7ed
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.release=enabled
+org.eclipse.jdt.core.compiler.source=11
diff --git a/persistence-modules/spring-data-redis/.settings/org.springframework.ide.eclipse.prefs b/persistence-modules/spring-data-redis/.settings/org.springframework.ide.eclipse.prefs
new file mode 100644
index 0000000000..a12794d68f
--- /dev/null
+++ b/persistence-modules/spring-data-redis/.settings/org.springframework.ide.eclipse.prefs
@@ -0,0 +1,2 @@
+boot.validation.initialized=true
+eclipse.preferences.version=1