diff --git a/persistence-modules/spring-data-jpa-repo/README.md b/persistence-modules/spring-data-jpa-repo/README.md
new file mode 100644
index 0000000000..284a7ac2b5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/README.md
@@ -0,0 +1,22 @@
+## Spring Data JPA - Repo
+
+This module contains articles about repositories in Spring Data JPA
+
+### Relevant Articles:
+- [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries)
+- [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries)
+- [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries)
+- [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save)
+- [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories)
+- [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories)
+- [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators)
+- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures)
+
+### 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-repo/pom.xml b/persistence-modules/spring-data-jpa-repo/pom.xml
new file mode 100644
index 0000000000..984bc1bdff
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+ spring-data-jpa-repo
+ spring-data-jpa-repo
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+ org.postgresql
+ postgresql
+
+
+
+ com.h2database
+ h2
+
+
+
+ org.springframework
+ spring-oxm
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/Application.java
new file mode 100644
index 0000000000..47a18b557f
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/Application.java
@@ -0,0 +1,17 @@
+package com.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+import com.baeldung.boot.daos.impl.ExtendedRepositoryImpl;
+
+@SpringBootApplication
+@EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class)
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemRepository.java
new file mode 100644
index 0000000000..0aebe34921
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemRepository.java
@@ -0,0 +1,16 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.domain.Item;
+
+@Repository
+public interface CustomItemRepository {
+
+ void deleteCustom(Item entity);
+
+ Item findItemById(Long id);
+
+ void findThenDelete(Long id);
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java
new file mode 100644
index 0000000000..832d61408c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/CustomItemTypeRepository.java
@@ -0,0 +1,13 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.domain.ItemType;
+
+@Repository
+public interface CustomItemTypeRepository {
+
+ void deleteCustom(ItemType entity);
+
+ void findThenDelete(Long id);
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java
new file mode 100644
index 0000000000..adb2af4320
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedRepository.java
@@ -0,0 +1,14 @@
+package com.baeldung.boot.daos;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.repository.NoRepositoryBean;
+
+@NoRepositoryBean
+public interface ExtendedRepository extends JpaRepository {
+
+ List findByAttributeContainsText(String attributeName, String text);
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java
new file mode 100644
index 0000000000..c9b0192536
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ExtendedStudentRepository.java
@@ -0,0 +1,6 @@
+package com.baeldung.boot.daos;
+
+import com.baeldung.boot.domain.Student;
+
+public interface ExtendedStudentRepository extends ExtendedRepository {
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/InventoryRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/InventoryRepository.java
new file mode 100644
index 0000000000..606f3993d5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/InventoryRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.data.repository.CrudRepository;
+
+import com.baeldung.boot.domain.MerchandiseEntity;
+
+public interface InventoryRepository extends CrudRepository {
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java
new file mode 100644
index 0000000000..413c09e968
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ItemTypeRepository.java
@@ -0,0 +1,10 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.domain.ItemType;
+
+@Repository
+public interface ItemTypeRepository extends JpaRepository, CustomItemTypeRepository, CustomItemRepository {
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/LocationRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/LocationRepository.java
new file mode 100644
index 0000000000..697ce295d0
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/LocationRepository.java
@@ -0,0 +1,10 @@
+package com.baeldung.boot.daos;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.domain.Location;
+
+@Repository
+public interface LocationRepository extends JpaRepository {
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java
new file mode 100644
index 0000000000..3a2ea3cda5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/ReadOnlyLocationRepository.java
@@ -0,0 +1,15 @@
+package com.baeldung.boot.daos;
+
+import java.util.Optional;
+
+import org.springframework.data.repository.Repository;
+
+import com.baeldung.boot.domain.Location;
+
+@org.springframework.stereotype.Repository
+public interface ReadOnlyLocationRepository extends Repository {
+
+ Optional findById(Long id);
+
+ Location save(Location location);
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/StoreRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/StoreRepository.java
new file mode 100644
index 0000000000..ae13f75f66
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/StoreRepository.java
@@ -0,0 +1,13 @@
+package com.baeldung.boot.daos;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.domain.Store;
+
+@Repository
+public interface StoreRepository extends JpaRepository {
+ List findStoreByLocationId(Long locationId);
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemRepositoryImpl.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemRepositoryImpl.java
new file mode 100644
index 0000000000..820a2cdd41
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemRepositoryImpl.java
@@ -0,0 +1,33 @@
+package com.baeldung.boot.daos.impl;
+
+import javax.persistence.EntityManager;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.daos.CustomItemRepository;
+import com.baeldung.boot.domain.Item;
+
+@Repository
+public class CustomItemRepositoryImpl implements CustomItemRepository {
+
+ @Autowired
+ private EntityManager entityManager;
+
+ @Override
+ public void deleteCustom(Item item) {
+ entityManager.remove(item);
+ }
+
+ @Override
+ public Item findItemById(Long id) {
+ return entityManager.find(Item.class, id);
+ }
+
+ @Override
+ public void findThenDelete(Long id) {
+ final Item item = entityManager.find(Item.class, id);
+ entityManager.remove(item);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java
new file mode 100644
index 0000000000..e057f36b26
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/CustomItemTypeRepositoryImpl.java
@@ -0,0 +1,27 @@
+package com.baeldung.boot.daos.impl;
+
+import javax.persistence.EntityManager;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.boot.daos.CustomItemTypeRepository;
+import com.baeldung.boot.domain.ItemType;
+
+@Repository
+public class CustomItemTypeRepositoryImpl implements CustomItemTypeRepository {
+
+ @Autowired
+ private EntityManager entityManager;
+
+ @Override
+ public void deleteCustom(ItemType itemType) {
+ entityManager.remove(itemType);
+ }
+
+ @Override
+ public void findThenDelete(Long id) {
+ ItemType itemTypeToDelete = entityManager.find(ItemType.class, id);
+ entityManager.remove(itemTypeToDelete);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java
new file mode 100644
index 0000000000..fbe6695844
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/daos/impl/ExtendedRepositoryImpl.java
@@ -0,0 +1,37 @@
+package com.baeldung.boot.daos.impl;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+import javax.transaction.Transactional;
+
+import org.springframework.data.jpa.repository.support.JpaEntityInformation;
+import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
+
+import com.baeldung.boot.daos.ExtendedRepository;
+
+public class ExtendedRepositoryImpl extends SimpleJpaRepository implements ExtendedRepository {
+
+ private EntityManager entityManager;
+
+ public ExtendedRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
+ super(entityInformation, entityManager);
+ this.entityManager = entityManager;
+ }
+
+ @Transactional
+ public List findByAttributeContainsText(String attributeName, String text) {
+ CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+ CriteriaQuery query = builder.createQuery(getDomainClass());
+ Root root = query.from(getDomainClass());
+ query.select(root).where(builder.like(root. get(attributeName), "%" + text + "%"));
+ TypedQuery q = entityManager.createQuery(query);
+ return q.getResultList();
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Item.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Item.java
new file mode 100644
index 0000000000..8ac06af15a
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Item.java
@@ -0,0 +1,81 @@
+package com.baeldung.boot.domain;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class Item {
+
+ private String color;
+ private String grade;
+
+ @Id
+ private Long id;
+
+ @ManyToOne
+ private ItemType itemType;
+
+ private String name;
+ private BigDecimal price;
+ @ManyToOne
+ private Store store;
+
+ public String getColor() {
+ return color;
+ }
+
+ public String getGrade() {
+ return grade;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public ItemType getItemType() {
+ return itemType;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public Store getStore() {
+ return store;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+ public void setGrade(String grade) {
+ this.grade = grade;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setItemType(ItemType itemType) {
+ this.itemType = itemType;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setPrice(BigDecimal price) {
+ this.price = price;
+ }
+
+ public void setStore(Store store) {
+ this.store = store;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/ItemType.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/ItemType.java
new file mode 100644
index 0000000000..8a52a9847c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/ItemType.java
@@ -0,0 +1,46 @@
+package com.baeldung.boot.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+
+@Entity
+public class ItemType {
+
+ @Id
+ private Long id;
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinColumn(name = "ITEM_TYPE_ID")
+ private List- items = new ArrayList<>();
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public List
- getItems() {
+ return items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setItems(List
- items) {
+ this.items = items;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/KVTag.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/KVTag.java
new file mode 100644
index 0000000000..1901f43c0a
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/KVTag.java
@@ -0,0 +1,34 @@
+package com.baeldung.boot.domain;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class KVTag {
+ private String key;
+ private String value;
+
+ public KVTag() {
+ }
+
+ public KVTag(String key, String value) {
+ super();
+ this.key = key;
+ this.value = value;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Location.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Location.java
new file mode 100644
index 0000000000..9c1b93d551
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Location.java
@@ -0,0 +1,55 @@
+package com.baeldung.boot.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+
+@Entity
+public class Location {
+
+ private String city;
+ private String country;
+ @Id
+ private Long id;
+
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinColumn(name = "LOCATION_ID")
+ private List stores = new ArrayList<>();
+
+ public String getCity() {
+ return city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public List getStores() {
+ return stores;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setStores(List stores) {
+ this.stores = stores;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.java
new file mode 100644
index 0000000000..e94c23de86
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/MerchandiseEntity.java
@@ -0,0 +1,66 @@
+package com.baeldung.boot.domain;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.math.BigDecimal;
+
+@Entity
+public class MerchandiseEntity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String title;
+
+ private BigDecimal price;
+
+ private String brand;
+
+ public MerchandiseEntity() {
+ }
+
+ public MerchandiseEntity(String title, BigDecimal price) {
+ this.title = title;
+ this.price = price;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public void setPrice(BigDecimal price) {
+ this.price = price;
+ }
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ @Override
+ public String toString() {
+ return "MerchandiseEntity{" +
+ "id=" + id +
+ ", title='" + title + '\'' +
+ ", price=" + price +
+ ", brand='" + brand + '\'' +
+ '}';
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/SkillTag.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/SkillTag.java
new file mode 100644
index 0000000000..0933a3e6af
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/SkillTag.java
@@ -0,0 +1,30 @@
+package com.baeldung.boot.domain;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class SkillTag {
+ private String name;
+ private int value;
+
+ public SkillTag() {
+ }
+
+ public SkillTag(String name, int value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Store.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Store.java
new file mode 100644
index 0000000000..5b4b831cc7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Store.java
@@ -0,0 +1,76 @@
+package com.baeldung.boot.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+
+@Entity
+public class Store {
+
+ private Boolean active;
+ @Id
+ private Long id;
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinColumn(name = "STORE_ID")
+ private List
- items = new ArrayList<>();
+ private Long itemsSold;
+
+ @ManyToOne
+ private Location location;
+
+ private String name;
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public List
- getItems() {
+ return items;
+ }
+
+ public Long getItemsSold() {
+ return itemsSold;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public void setItems(List
- items) {
+ this.items = items;
+ }
+
+ public void setItemsSold(Long itemsSold) {
+ this.itemsSold = itemsSold;
+ }
+
+ public void setLocation(Location location) {
+ this.location = location;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Student.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Student.java
new file mode 100644
index 0000000000..1003167cc7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/boot/domain/Student.java
@@ -0,0 +1,74 @@
+package com.baeldung.boot.domain;
+
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+public class Student {
+
+ @Id
+ private long id;
+ private String name;
+
+ @ElementCollection
+ private List tags = new ArrayList<>();
+
+ @ElementCollection
+ private List skillTags = new ArrayList<>();
+
+ @ElementCollection
+ private List kvTags = new ArrayList<>();
+
+ public Student() {
+ }
+
+ public Student(long id, String name) {
+ super();
+ 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;
+ }
+
+ public List getTags() {
+ return tags;
+ }
+
+ public void setTags(List tags) {
+ this.tags.addAll(tags);
+ }
+
+ public List getSkillTags() {
+ return skillTags;
+ }
+
+ public void setSkillTags(List skillTags) {
+ this.skillTags.addAll(skillTags);
+ }
+
+ public List getKVTags() {
+ return this.kvTags;
+ }
+
+ public void setKVTags(List kvTags) {
+ this.kvTags.addAll(kvTags);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/config/JpaPopulators.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/config/JpaPopulators.java
new file mode 100644
index 0000000000..24348d31c5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/config/JpaPopulators.java
@@ -0,0 +1,35 @@
+package com.baeldung.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean;
+import org.springframework.data.repository.init.UnmarshallerRepositoryPopulatorFactoryBean;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+import com.baeldung.entity.Fruit;
+
+@Configuration
+public class JpaPopulators {
+
+ @Bean
+ public Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulator() throws Exception {
+ Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean();
+ factory.setResources(new Resource[] { new ClassPathResource("fruit-data.json") });
+ return factory;
+ }
+
+ @Bean
+ public UnmarshallerRepositoryPopulatorFactoryBean repositoryPopulator() {
+
+ Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
+ unmarshaller.setClassesToBeBound(Fruit.class);
+
+ UnmarshallerRepositoryPopulatorFactoryBean factory = new UnmarshallerRepositoryPopulatorFactoryBean();
+ factory.setUnmarshaller(unmarshaller);
+ factory.setResources(new Resource[] { new ClassPathResource("apple-fruit-data.xml"), new ClassPathResource("guava-fruit-data.xml") });
+ return factory;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java
new file mode 100644
index 0000000000..d7a1950305
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/QueryApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.derivedquery;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class QueryApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(QueryApplication.class, args);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java
new file mode 100644
index 0000000000..49e824f09f
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/entity/User.java
@@ -0,0 +1,70 @@
+package com.baeldung.derivedquery.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.time.ZonedDateTime;
+
+@Table(name = "users")
+@Entity
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Integer id;
+ private String name;
+ private Integer age;
+ private ZonedDateTime birthDate;
+ private Boolean active;
+
+ public User() {
+ }
+
+ public User(String name, Integer age, ZonedDateTime birthDate, Boolean active) {
+ this.name = name;
+ this.age = age;
+ this.birthDate = birthDate;
+ this.active = active;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public ZonedDateTime getBirthDate() {
+ return birthDate;
+ }
+
+ public void setBirthDate(ZonedDateTime birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java
new file mode 100644
index 0000000000..e613ee1531
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java
@@ -0,0 +1,60 @@
+package com.baeldung.derivedquery.repository;
+
+import com.baeldung.derivedquery.entity.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.List;
+
+public interface UserRepository extends JpaRepository {
+
+ List findByName(String name);
+
+ List findByNameIs(String name);
+
+ List findByNameEquals(String name);
+
+ List findByNameIsNull();
+
+ List findByNameNot(String name);
+
+ List findByNameIsNot(String name);
+
+ List findByNameStartingWith(String name);
+
+ List findByNameEndingWith(String name);
+
+ List findByNameContaining(String name);
+
+ List findByNameLike(String name);
+
+ List findByAgeLessThan(Integer age);
+
+ List findByAgeLessThanEqual(Integer age);
+
+ List findByAgeGreaterThan(Integer age);
+
+ List findByAgeGreaterThanEqual(Integer age);
+
+ List findByAgeBetween(Integer startAge, Integer endAge);
+
+ List findByBirthDateAfter(ZonedDateTime birthDate);
+
+ List findByBirthDateBefore(ZonedDateTime birthDate);
+
+ List findByActiveTrue();
+
+ List findByActiveFalse();
+
+ List findByAgeIn(Collection ages);
+
+ List findByNameOrBirthDate(String name, ZonedDateTime birthDate);
+
+ List findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);
+
+ List findByNameOrderByName(String name);
+
+ List findByNameOrderByNameDesc(String name);
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Fruit.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Fruit.java
new file mode 100644
index 0000000000..d45ac33db8
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Fruit.java
@@ -0,0 +1,40 @@
+package com.baeldung.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@Entity
+public class Fruit {
+
+ @Id
+ private long id;
+ private String name;
+ private String color;
+
+ 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 String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Passenger.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Passenger.java
new file mode 100644
index 0000000000..3aafbe9afa
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Passenger.java
@@ -0,0 +1,78 @@
+package com.baeldung.entity;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import java.util.Objects;
+
+@Entity
+public class Passenger {
+
+ @Id
+ @GeneratedValue
+ @Column(nullable = false)
+ private Long id;
+
+ @Basic(optional = false)
+ @Column(nullable = false)
+ private String firstName;
+
+ @Basic(optional = false)
+ @Column(nullable = false)
+ private String lastName;
+
+ private Passenger(String firstName, String lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public static Passenger from(String firstName, String lastName) {
+ return new Passenger(firstName, lastName);
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ @Override
+ public String toString() {
+ return "Passenger{" + "id=" + id + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ Passenger passenger = (Passenger) o;
+ return Objects.equals(firstName, passenger.firstName) && Objects.equals(lastName, passenger.lastName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(firstName, lastName);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Song.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Song.java
new file mode 100644
index 0000000000..395527c1eb
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/entity/Song.java
@@ -0,0 +1,75 @@
+package com.baeldung.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.time.LocalDateTime;
+
+@Entity
+public class Song {
+
+ @Id private long id;
+ private String name;
+ @Column(name = "length_in_seconds")
+ private int lengthInSeconds;
+ private String compositor;
+ private String singer;
+ private LocalDateTime released;
+ private String genre;
+
+ 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 int getLengthInSeconds() {
+ return lengthInSeconds;
+ }
+
+ public void setLengthInSeconds(int lengthInSeconds) {
+ this.lengthInSeconds = lengthInSeconds;
+ }
+
+ public String getCompositor() {
+ return compositor;
+ }
+
+ public void setCompositor(String compositor) {
+ this.compositor = compositor;
+ }
+
+ public String getSinger() {
+ return singer;
+ }
+
+ public void setSinger(String singer) {
+ this.singer = singer;
+ }
+
+ public LocalDateTime getReleased() {
+ return released;
+ }
+
+ public void setReleased(LocalDateTime released) {
+ this.released = released;
+ }
+
+ public String getGenre() {
+ return genre;
+ }
+
+ public void setGenre(String genre) {
+ this.genre = genre;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java
new file mode 100644
index 0000000000..311aea3001
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/LikeApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.like;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LikeApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LikeApplication.class, args);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java
new file mode 100644
index 0000000000..bba8bd35c4
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/model/Movie.java
@@ -0,0 +1,58 @@
+package com.baeldung.like.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Movie {
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private Long id;
+ private String title;
+ private String director;
+ private String rating;
+ private int duration;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getRating() {
+ return rating;
+ }
+
+ public void setRating(String rating) {
+ this.rating = rating;
+ }
+
+ public int getDuration() {
+ return duration;
+ }
+
+ public void setDuration(int duration) {
+ this.duration = duration;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java
new file mode 100644
index 0000000000..241bdd3306
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/like/repository/MovieRepository.java
@@ -0,0 +1,41 @@
+package com.baeldung.like.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+
+import com.baeldung.like.model.Movie;
+
+public interface MovieRepository extends CrudRepository {
+
+ List findByTitleContaining(String title);
+
+ List findByTitleLike(String title);
+
+ List findByTitleContains(String title);
+
+ List findByTitleIsContaining(String title);
+
+ List findByRatingStartsWith(String rating);
+
+ List findByDirectorEndsWith(String director);
+
+ List findByTitleContainingIgnoreCase(String title);
+
+ List findByRatingNotContaining(String rating);
+
+ List findByDirectorNotLike(String director);
+
+ @Query("SELECT m FROM Movie m WHERE m.title LIKE %:title%")
+ List searchByTitleLike(@Param("title") String title);
+
+ @Query("SELECT m FROM Movie m WHERE m.rating LIKE ?1%")
+ List searchByRatingStartsWith(String rating);
+
+ //Escaping works in SpringBoot >= 2.4.1
+ //@Query("SELECT m FROM Movie m WHERE m.director LIKE %?#{escape([0])} escape ?#{escapeCharacter()}")
+ @Query("SELECT m FROM Movie m WHERE m.director LIKE %:#{[0]}")
+ List searchByDirectorEndsWith(String director);
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/FruitRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/FruitRepository.java
new file mode 100644
index 0000000000..5055252adf
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/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-repo/src/main/java/com/baeldung/repository/PassengerRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/PassengerRepository.java
new file mode 100644
index 0000000000..a295a74f1b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/PassengerRepository.java
@@ -0,0 +1,14 @@
+package com.baeldung.repository;
+
+import com.baeldung.entity.Passenger;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Repository
+interface PassengerRepository extends JpaRepository {
+
+ List findByFirstNameIgnoreCase(String firstName);
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/SongRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/SongRepository.java
new file mode 100644
index 0000000000..6faed411d3
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/repository/SongRepository.java
@@ -0,0 +1,22 @@
+package com.baeldung.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.entity.Song;
+
+@Repository
+public interface SongRepository extends JpaRepository {
+
+ List findByNameLike(String name);
+
+ List findByNameNotLike(String name);
+
+ List findByNameStartingWith(String startingWith);
+
+ List findByNameEndingWith(String endingWith);
+
+ List findBySingerContaining(String singer);
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java
new file mode 100644
index 0000000000..5f05764e21
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.storedprocedure;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class StoredProcedureApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StoredProcedureApplication.class, args);
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java
new file mode 100644
index 0000000000..6aef600d01
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/controller/CarController.java
@@ -0,0 +1,47 @@
+package com.baeldung.storedprocedure.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.storedprocedure.entity.Car;
+import com.baeldung.storedprocedure.service.CarService;
+
+@RestController
+public class CarController {
+ @Autowired
+ private CarService carService;
+
+ @GetMapping(path = "/modelcount")
+ public long getTotalCarsByModel(@RequestParam("model") String model) {
+ return carService.getTotalCarsByModel(model);
+ }
+
+ @GetMapping(path = "/modelcountP")
+ public long getTotalCarsByModelProcedureName(@RequestParam("model") String model) {
+ return carService.getTotalCarsByModelProcedureName(model);
+ }
+
+ @GetMapping(path = "/modelcountV")
+ public long getTotalCarsByModelVaue(@RequestParam("model") String model) {
+ return carService.getTotalCarsByModelValue(model);
+ }
+
+ @GetMapping(path = "/modelcountEx")
+ public long getTotalCarsByModelExplicit(@RequestParam("model") String model) {
+ return carService.getTotalCarsByModelExplicit(model);
+ }
+
+ @GetMapping(path = "/modelcountEn")
+ public long getTotalCarsByModelEntity(@RequestParam("model") String model) {
+ return carService.getTotalCarsByModelEntity(model);
+ }
+
+ @GetMapping(path = "/carsafteryear")
+ public List findCarsAfterYear(@RequestParam("year") Integer year) {
+ return carService.findCarsAfterYear(year);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java
new file mode 100644
index 0000000000..2817c25ff7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/entity/Car.java
@@ -0,0 +1,41 @@
+package com.baeldung.storedprocedure.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedStoredProcedureQuery;
+import javax.persistence.StoredProcedureParameter;
+import javax.persistence.ParameterMode;
+
+@Entity
+@NamedStoredProcedureQuery(name = "Car.getTotalCardsbyModelEntity", procedureName = "GET_TOTAL_CARS_BY_MODEL", parameters = {
+ @StoredProcedureParameter(mode = ParameterMode.IN, name = "model_in", type = String.class),
+ @StoredProcedureParameter(mode = ParameterMode.OUT, name = "count_out", type = Integer.class) })
+
+public class Car {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column
+ private long id;
+
+ @Column
+ private String model;
+
+ @Column
+ private Integer year;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public Integer getYear() {
+ return year;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java
new file mode 100644
index 0000000000..3d9428628e
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java
@@ -0,0 +1,34 @@
+package com.baeldung.storedprocedure.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.jpa.repository.query.Procedure;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.storedprocedure.entity.Car;
+
+@Repository
+public interface CarRepository extends JpaRepository {
+
+ @Procedure
+ int GET_TOTAL_CARS_BY_MODEL(String model);
+
+ @Procedure("GET_TOTAL_CARS_BY_MODEL")
+ int getTotalCarsByModel(String model);
+
+ @Procedure(procedureName = "GET_TOTAL_CARS_BY_MODEL")
+ int getTotalCarsByModelProcedureName(String model);
+
+ @Procedure(value = "GET_TOTAL_CARS_BY_MODEL")
+ int getTotalCarsByModelValue(String model);
+
+ @Procedure(name = "Car.getTotalCardsbyModelEntity")
+ int getTotalCarsByModelEntiy(@Param("model_in") String model);
+
+ @Query(value = "CALL FIND_CARS_AFTER_YEAR(:year_in);", nativeQuery = true)
+ List findCarsAfterYear(@Param("year_in") Integer year_in);
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java
new file mode 100644
index 0000000000..104f46e324
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/storedprocedure/service/CarService.java
@@ -0,0 +1,39 @@
+package com.baeldung.storedprocedure.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.storedprocedure.entity.Car;
+import com.baeldung.storedprocedure.repository.CarRepository;
+
+@Service
+public class CarService {
+ @Autowired
+ private CarRepository carRepository;
+
+ public int getTotalCarsByModel(String model) {
+ return carRepository.getTotalCarsByModel(model);
+ }
+
+ public int getTotalCarsByModelProcedureName(String model) {
+ return carRepository.getTotalCarsByModelProcedureName(model);
+ }
+
+ public int getTotalCarsByModelValue(String model) {
+ return carRepository.getTotalCarsByModelValue(model);
+ }
+
+ public int getTotalCarsByModelExplicit(String model) {
+ return carRepository.GET_TOTAL_CARS_BY_MODEL(model);
+ }
+
+ public int getTotalCarsByModelEntity(String model) {
+ return carRepository.getTotalCarsByModelEntiy(model);
+ }
+
+ public List findCarsAfterYear(Integer year) {
+ return carRepository.findCarsAfterYear(year);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/apple-fruit-data.xml b/persistence-modules/spring-data-jpa-repo/src/main/resources/apple-fruit-data.xml
new file mode 100644
index 0000000000..d87ae28f1e
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/apple-fruit-data.xml
@@ -0,0 +1,7 @@
+
+
+
+ 1
+ apple
+ red
+
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties
new file mode 100644
index 0000000000..65d7b0bf29
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+spring.jpa.show-sql=true
+#MySql
+#spring.datasource.url=jdbc:mysql://localhost:3306/baeldung
+#spring.datasource.username=baeldung
+#spring.datasource.password=baeldung
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql b/persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql
new file mode 100644
index 0000000000..bb4ab2a86e
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/car-mysql.sql
@@ -0,0 +1,27 @@
+DROP TABLE IF EXISTS car;
+
+CREATE TABLE car (id int(10) NOT NULL AUTO_INCREMENT,
+ model varchar(50) NOT NULL,
+ year int(4) NOT NULL,
+ PRIMARY KEY (id));
+
+INSERT INTO car (model, year) VALUES ('BMW', 2000);
+INSERT INTO car (model, year) VALUES ('BENZ', 2010);
+INSERT INTO car (model, year) VALUES ('PORCHE', 2005);
+INSERT INTO car (model, year) VALUES ('PORCHE', 2004);
+
+DELIMITER $$
+
+DROP PROCEDURE IF EXISTS FIND_CARS_AFTER_YEAR$$
+CREATE PROCEDURE FIND_CARS_AFTER_YEAR(IN year_in INT)
+BEGIN
+ SELECT * FROM car WHERE year >= year_in ORDER BY year;
+END$$
+
+DROP PROCEDURE IF EXISTS GET_TOTAL_CARS_BY_MODEL$$
+CREATE PROCEDURE GET_TOTAL_CARS_BY_MODEL(IN model_in VARCHAR(50), OUT count_out INT)
+BEGIN
+ SELECT COUNT(*) into count_out from car WHERE model = model_in;
+END$$
+
+DELIMITER ;
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/fruit-data.json b/persistence-modules/spring-data-jpa-repo/src/main/resources/fruit-data.json
new file mode 100644
index 0000000000..6dc44e2586
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/fruit-data.json
@@ -0,0 +1,14 @@
+[
+ {
+ "_class": "com.baeldung.entity.Fruit",
+ "name": "apple",
+ "color": "red",
+ "id": 1
+ },
+ {
+ "_class": "com.baeldung.entity.Fruit",
+ "name": "guava",
+ "color": "green",
+ "id": 2
+ }
+]
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/guava-fruit-data.xml b/persistence-modules/spring-data-jpa-repo/src/main/resources/guava-fruit-data.xml
new file mode 100644
index 0000000000..ffd75bb4bb
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/guava-fruit-data.xml
@@ -0,0 +1,7 @@
+
+
+
+ 2
+ guava
+ green
+
diff --git a/persistence-modules/spring-data-jpa-repo/src/main/resources/import_entities.sql b/persistence-modules/spring-data-jpa-repo/src/main/resources/import_entities.sql
new file mode 100644
index 0000000000..6282fd1481
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/main/resources/import_entities.sql
@@ -0,0 +1,17 @@
+insert into location (id, country, city) values (1, 'Country X', 'City One');
+insert into location (id, country, city) values (2, 'Country X', 'City Two');
+insert into location (id, country, city) values (3, 'Country X', 'City Three');
+
+insert into store (id, name, location_id, items_sold, active) values (1, 'Store One', 3, 130000, true);
+insert into store (id, name, location_id, items_sold, active) values (2, 'Store Two', 1, 170000, false);
+
+insert into item_type (id, name) values (1, 'Food');
+insert into item_type (id, name) values (2, 'Furniture');
+insert into item_type (id, name) values (3, 'Electronics');
+
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (1, 'Food Item One', 1, 1, 100, 'A', 'Color x');
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (2, 'Furniture Item One', 1, 2, 2500, 'B', 'Color y');
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (3, 'Food Item Two', 1, 1, 35, 'A', 'Color z');
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (5, 'Furniture Item Two', 2, 2, 1600, 'A', 'Color w');
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (6, 'Food Item Three', 2, 1, 5, 'B', 'Color a');
+insert into item (id, name, store_id, item_type_id, price, grade, color) values (7, 'Electronics Item One', 2, 3, 999, 'B', 'Color b');
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..b367b5fdca
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/ExtendedStudentRepositoryIntegrationTest.java
@@ -0,0 +1,41 @@
+package com.baeldung.boot.daos;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.junit.Before;
+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.SpringRunner;
+
+import com.baeldung.Application;
+import com.baeldung.boot.domain.Student;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = {Application.class})
+@DirtiesContext
+public class ExtendedStudentRepositoryIntegrationTest {
+ @Resource
+ private ExtendedStudentRepository extendedStudentRepository;
+
+ @Before
+ public void setup() {
+ Student student = new Student(1, "john");
+ extendedStudentRepository.save(student);
+ Student student2 = new Student(2, "johnson");
+ extendedStudentRepository.save(student2);
+ Student student3 = new Student(3, "tom");
+ extendedStudentRepository.save(student3);
+ }
+
+ @Test
+ public void givenStudents_whenFindByName_thenGetOk() {
+ List students = extendedStudentRepository.findByAttributeContainsText("name", "john");
+ assertThat(students.size()).isEqualTo(2);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..22e2c81739
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/InventoryRepositoryIntegrationTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.boot.daos;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.math.BigDecimal;
+
+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.Application;
+import com.baeldung.boot.domain.MerchandiseEntity;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes=Application.class)
+public class InventoryRepositoryIntegrationTest {
+
+ private static final String ORIGINAL_TITLE = "Pair of Pants";
+ private static final String UPDATED_TITLE = "Branded Luxury Pants";
+ private static final String UPDATED_BRAND = "Armani";
+ private static final String ORIGINAL_SHORTS_TITLE = "Pair of Shorts";
+
+ @Autowired
+ private InventoryRepository repository;
+
+ @Test
+ public void shouldCreateNewEntryInDB() {
+ MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE);
+ pants = repository.save(pants);
+
+ MerchandiseEntity shorts = new MerchandiseEntity(ORIGINAL_SHORTS_TITLE, new BigDecimal(3));
+ shorts = repository.save(shorts);
+
+ assertNotNull(pants.getId());
+ assertNotNull(shorts.getId());
+ assertNotEquals(pants.getId(), shorts.getId());
+ }
+
+ @Test
+ public void shouldUpdateExistingEntryInDB() {
+ MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE);
+ pants = repository.save(pants);
+
+ Long originalId = pants.getId();
+
+ pants.setTitle(UPDATED_TITLE);
+ pants.setPrice(BigDecimal.TEN);
+ pants.setBrand(UPDATED_BRAND);
+
+ MerchandiseEntity result = repository.save(pants);
+
+ assertEquals(originalId, result.getId());
+ assertEquals(UPDATED_TITLE, result.getTitle());
+ assertEquals(BigDecimal.TEN, result.getPrice());
+ assertEquals(UPDATED_BRAND, result.getBrand());
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java
new file mode 100644
index 0000000000..9e4b78dce3
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/boot/daos/JpaRepositoriesIntegrationTest.java
@@ -0,0 +1,93 @@
+package com.baeldung.boot.daos;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.boot.domain.Item;
+import com.baeldung.boot.domain.ItemType;
+import com.baeldung.boot.domain.Location;
+import com.baeldung.boot.domain.Store;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest(properties="spring.datasource.data=classpath:import_entities.sql")
+public class JpaRepositoriesIntegrationTest {
+ @Autowired
+ private LocationRepository locationRepository;
+ @Autowired
+ private StoreRepository storeRepository;
+ @Autowired
+ private ItemTypeRepository compositeRepository;
+ @Autowired
+ private ReadOnlyLocationRepository readOnlyRepository;
+
+ @Test
+ public void whenSaveLocation_ThenGetSameLocation() {
+ Location location = new Location();
+ location.setId(100L);
+ location.setCountry("Country H");
+ location.setCity("City Hundred");
+ location = locationRepository.saveAndFlush(location);
+
+ Location otherLocation = locationRepository.getOne(location.getId());
+ assertEquals("Country H", otherLocation.getCountry());
+ assertEquals("City Hundred", otherLocation.getCity());
+
+ locationRepository.delete(otherLocation);
+ }
+
+ @Test
+ public void givenLocationId_whenFindStores_thenGetStores() {
+ List stores = storeRepository.findStoreByLocationId(1L);
+ assertEquals(1, stores.size());
+ }
+
+ @Test
+ public void givenItemTypeId_whenDeleted_ThenItemTypeDeleted() {
+ Optional itemType = compositeRepository.findById(1L);
+ assertTrue(itemType.isPresent());
+ compositeRepository.deleteCustom(itemType.get());
+ itemType = compositeRepository.findById(1L);
+ assertFalse(itemType.isPresent());
+ }
+
+ @Test
+ public void givenItemId_whenUsingCustomRepo_ThenDeleteAppropriateEntity() {
+ Item item = compositeRepository.findItemById(1L);
+ assertNotNull(item);
+ compositeRepository.deleteCustom(item);
+ item = compositeRepository.findItemById(1L);
+ assertNull(item);
+ }
+
+ @Test
+ public void givenItemAndItemType_WhenAmbiguousDeleteCalled_ThenItemTypeDeletedAndNotItem() {
+ Optional itemType = compositeRepository.findById(1L);
+ assertTrue(itemType.isPresent());
+ Item item = compositeRepository.findItemById(2L);
+ assertNotNull(item);
+
+ compositeRepository.findThenDelete(1L);
+ Optional sameItemType = compositeRepository.findById(1L);
+ assertFalse(sameItemType.isPresent());
+ Item sameItem = compositeRepository.findItemById(2L);
+ assertNotNull(sameItem);
+ }
+
+ @Test
+ public void whenCreatingReadOnlyRepo_thenHaveOnlyReadOnlyOperationsAvailable() {
+ Optional location = readOnlyRepository.findById(1L);
+ assertNotNull(location);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..2a6e166b88
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryIntegrationTest.java
@@ -0,0 +1,172 @@
+package com.baeldung.derivedquery.repository;
+
+import com.baeldung.derivedquery.QueryApplication;
+import com.baeldung.derivedquery.entity.User;
+import org.junit.After;
+import org.junit.Before;
+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 java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = QueryApplication.class)
+public class UserRepositoryIntegrationTest {
+
+ private static final String USER_NAME_ADAM = "Adam";
+ private static final String USER_NAME_EVE = "Eve";
+ private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now();
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Before
+ public void setUp() {
+
+ User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true);
+ User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false);
+ User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true);
+ User user4 = new User(null, 30, BIRTHDATE, false);
+
+ userRepository.saveAll(Arrays.asList(user1, user2, user3, user4));
+ }
+
+ @After
+ public void tearDown() {
+
+ userRepository.deleteAll();
+ }
+
+ @Test
+ public void whenFindByName_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByName(USER_NAME_ADAM).size());
+ }
+
+ @Test
+ public void whenFindByNameIsNull_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameIsNull().size());
+ }
+
+ @Test
+ public void whenFindByNameNot_thenReturnsCorrectResult() {
+
+ assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM).get(0).getName());
+ }
+
+ @Test
+ public void whenFindByNameStartingWith_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByNameStartingWith("A").size());
+ }
+
+ @Test
+ public void whenFindByNameEndingWith_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameEndingWith("e").size());
+ }
+
+ @Test
+ public void whenByNameContaining_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameContaining("v").size());
+ }
+
+
+ @Test
+ public void whenByNameLike_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByNameEndingWith("m").size());
+ }
+
+ @Test
+ public void whenByAgeLessThan_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByAgeLessThan(25).size());
+ }
+
+
+ @Test
+ public void whenByAgeLessThanEqual_thenReturnsCorrectResult() {
+
+ assertEquals(3, userRepository.findByAgeLessThanEqual(25).size());
+ }
+
+ @Test
+ public void whenByAgeGreaterThan_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByAgeGreaterThan(25).size());
+ }
+
+ @Test
+ public void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByAgeGreaterThanEqual(25).size());
+ }
+
+ @Test
+ public void whenByAgeBetween_thenReturnsCorrectResult() {
+
+ assertEquals(4, userRepository.findByAgeBetween(20, 30).size());
+ }
+
+ @Test
+ public void whenByBirthDateAfter_thenReturnsCorrectResult() {
+
+ final ZonedDateTime yesterday = BIRTHDATE.minusDays(1);
+ assertEquals(4, userRepository.findByBirthDateAfter(yesterday).size());
+ }
+
+ @Test
+ public void whenByBirthDateBefore_thenReturnsCorrectResult() {
+
+ final ZonedDateTime yesterday = BIRTHDATE.minusDays(1);
+ assertEquals(0, userRepository.findByBirthDateBefore(yesterday).size());
+ }
+
+ @Test
+ public void whenByActiveTrue_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByActiveTrue().size());
+ }
+
+ @Test
+ public void whenByActiveFalse_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByActiveFalse().size());
+ }
+
+
+ @Test
+ public void whenByAgeIn_thenReturnsCorrectResult() {
+
+ final List ages = Arrays.asList(20, 25);
+ assertEquals(3, userRepository.findByAgeIn(ages).size());
+ }
+
+ @Test
+ public void whenByNameOrBirthDate() {
+
+ assertEquals(4, userRepository.findByNameOrBirthDate(USER_NAME_ADAM, BIRTHDATE).size());
+ }
+
+ @Test
+ public void whenByNameOrBirthDateAndActive() {
+
+ assertEquals(3, userRepository.findByNameOrBirthDateAndActive(USER_NAME_ADAM, BIRTHDATE, false).size());
+ }
+
+ @Test
+ public void whenByNameOrderByName() {
+
+ assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM).size());
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..cc96b638ab
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/like/MovieRepositoryIntegrationTest.java
@@ -0,0 +1,87 @@
+package com.baeldung.like;
+
+import com.baeldung.like.model.Movie;
+import com.baeldung.like.repository.MovieRepository;
+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.jdbc.Sql;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
+
+@RunWith(SpringRunner.class)
+@Sql(scripts = { "/test-movie-data.sql" })
+@SpringBootTest(classes = LikeApplication.class)
+@Sql(scripts = "/test-movie-cleanup.sql", executionPhase = AFTER_TEST_METHOD)
+public class MovieRepositoryIntegrationTest {
+ @Autowired
+ private MovieRepository movieRepository;
+
+ @Test
+ public void givenPartialTitle_WhenFindByTitleContaining_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByTitleContaining("in");
+ assertEquals(3, results.size());
+
+ results = movieRepository.findByTitleLike("%in%");
+ assertEquals(3, results.size());
+
+ results = movieRepository.findByTitleIsContaining("in");
+ assertEquals(3, results.size());
+
+ results = movieRepository.findByTitleContains("in");
+ assertEquals(3, results.size());
+ }
+
+ @Test
+ public void givenStartOfRating_WhenFindByRatingStartsWith_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByRatingStartsWith("PG");
+ assertEquals(6, results.size());
+ }
+
+ @Test
+ public void givenLastName_WhenFindByDirectorEndsWith_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByDirectorEndsWith("Burton");
+ assertEquals(1, results.size());
+ }
+
+ @Test
+ public void givenPartialTitle_WhenFindByTitleContainingIgnoreCase_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByTitleContainingIgnoreCase("the");
+ assertEquals(2, results.size());
+ }
+
+ @Test
+ public void givenPartialTitle_WhenSearchByTitleLike_ThenMoviesShouldReturn() {
+ List results = movieRepository.searchByTitleLike("in");
+ assertEquals(3, results.size());
+ }
+
+ @Test
+ public void givenStartOfRating_SearchFindByRatingStartsWith_ThenMoviesShouldReturn() {
+ List results = movieRepository.searchByRatingStartsWith("PG");
+ assertEquals(6, results.size());
+ }
+
+ @Test
+ public void givenLastName_WhenSearchByDirectorEndsWith_ThenMoviesShouldReturn() {
+ List results = movieRepository.searchByDirectorEndsWith("Burton");
+ assertEquals(1, results.size());
+ }
+
+ @Test
+ public void givenPartialRating_findByRatingNotContaining_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByRatingNotContaining("PG");
+ assertEquals(1, results.size());
+ }
+
+ @Test
+ public void givenPartialDirector_WhenFindByDirectorNotLike_ThenMoviesShouldReturn() {
+ List results = movieRepository.findByDirectorNotLike("An%");
+ assertEquals(5, results.size());
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/FruitPopulatorIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/FruitPopulatorIntegrationTest.java
new file mode 100644
index 0000000000..4d3661e717
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/FruitPopulatorIntegrationTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.repository;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+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.entity.Fruit;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class FruitPopulatorIntegrationTest {
+
+ @Autowired
+ private FruitRepository fruitRepository;
+
+ @Test
+ public void givenFruitJsonPopulatorThenShouldInsertRecordOnStart() {
+
+ List fruits = fruitRepository.findAll();
+ assertEquals("record count is not matching", 2, fruits.size());
+
+ fruits.forEach(fruit -> {
+ if (1 == fruit.getId()) {
+ assertEquals("apple", fruit.getName());
+ assertEquals("red", fruit.getColor());
+ } else if (2 == fruit.getId()) {
+ assertEquals("guava", fruit.getName());
+ assertEquals("green", fruit.getColor());
+ }
+ });
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..37fcef7dab
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/PassengerRepositoryIntegrationTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.repository;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.core.IsNot.not;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.entity.Passenger;
+
+@DataJpaTest
+@RunWith(SpringRunner.class)
+public class PassengerRepositoryIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+ @Autowired
+ private PassengerRepository repository;
+
+ @Before
+ public void before() {
+ entityManager.persist(Passenger.from("Jill", "Smith"));
+ entityManager.persist(Passenger.from("Eve", "Jackson"));
+ entityManager.persist(Passenger.from("Fred", "Bloggs"));
+ entityManager.persist(Passenger.from("Ricki", "Bobbie"));
+ entityManager.persist(Passenger.from("Siya", "Kolisi"));
+ }
+
+ @Test
+ public void givenPassengers_whenMatchingIgnoreCase_thenExpectedReturned() {
+ Passenger jill = Passenger.from("Jill", "Smith");
+ Passenger eve = Passenger.from("Eve", "Jackson");
+ Passenger fred = Passenger.from("Fred", "Bloggs");
+ Passenger siya = Passenger.from("Siya", "Kolisi");
+ Passenger ricki = Passenger.from("Ricki", "Bobbie");
+
+ List passengers = repository.findByFirstNameIgnoreCase("FRED");
+
+ assertThat(passengers, contains(fred));
+ assertThat(passengers, not(contains(eve)));
+ assertThat(passengers, not(contains(siya)));
+ assertThat(passengers, not(contains(jill)));
+ assertThat(passengers, not(contains(ricki)));
+
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..19362acd44
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java
@@ -0,0 +1,59 @@
+package com.baeldung.repository;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+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.jdbc.Sql;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.entity.Song;
+import com.baeldung.repository.SongRepository;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Sql(scripts = { "/test-song-data.sql" })
+public class SongRepositoryIntegrationTest {
+
+ @Autowired private SongRepository songRepository;
+
+ @Transactional
+ @Test
+ public void givenSong_WhenFindLikeByName_ThenShouldReturnOne() {
+ List songs = songRepository.findByNameLike("Despacito");
+ assertEquals(1, songs.size());
+ }
+
+ @Transactional
+ @Test
+ public void givenSong_WhenFindByNameNotLike_thenShouldReturn3Songs() {
+ List songs = songRepository.findByNameNotLike("Despacito");
+ assertEquals(5, songs.size());
+ }
+
+ @Transactional
+ @Test
+ public void givenSong_WhenFindByNameStartingWith_thenShouldReturn2Songs() {
+ List songs = songRepository.findByNameStartingWith("Co");
+ assertEquals(2, songs.size());
+ }
+
+ @Transactional
+ @Test
+ public void givenSong_WhenFindByNameEndingWith_thenShouldReturn2Songs() {
+ List songs = songRepository.findByNameEndingWith("Life");
+ assertEquals(2, songs.size());
+ }
+
+ @Transactional
+ @Test
+ public void givenSong_WhenFindBySingerContaining_thenShouldReturn2Songs() {
+ List songs = songRepository.findBySingerContaining("Luis");
+ assertEquals(2, songs.size());
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/application-test.properties b/persistence-modules/spring-data-jpa-repo/src/test/resources/application-test.properties
new file mode 100644
index 0000000000..f9497c8f37
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/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-repo/src/test/resources/test-movie-cleanup.sql b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-cleanup.sql
new file mode 100644
index 0000000000..90aa15307c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-cleanup.sql
@@ -0,0 +1 @@
+DELETE FROM Movie;
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-data.sql b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-data.sql
new file mode 100644
index 0000000000..37f8e4fe64
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-movie-data.sql
@@ -0,0 +1,7 @@
+INSERT INTO movie(id, title, director, rating, duration) VALUES(1, 'Godzilla: King of the Monsters', ' Michael Dougherty', 'PG-13', 132);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(2, 'Avengers: Endgame', 'Anthony Russo', 'PG-13', 181);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(3, 'Captain Marvel', 'Anna Boden', 'PG-13', 123);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(4, 'Dumbo', 'Tim Burton', 'PG', 112);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(5, 'Booksmart', 'Olivia Wilde', 'R', 102);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(6, 'Aladdin', 'Guy Ritchie', 'PG', 128);
+INSERT INTO movie(id, title, director, rating, duration) VALUES(7, 'The Sun Is Also a Star', 'Ry Russo-Young', 'PG-13', 100);
diff --git a/persistence-modules/spring-data-jpa-repo/src/test/resources/test-song-data.sql b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-song-data.sql
new file mode 100644
index 0000000000..5a2b1a5555
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-repo/src/test/resources/test-song-data.sql
@@ -0,0 +1,8 @@
+INSERT INTO song(id,name,length_in_seconds,compositor,singer,released,genre)
+VALUES
+(1,'Despacito',209,'Luis Fonsi','Luis Fonsi, Daddy Yankee','2017-01-12','Reggaeton'),
+(2,'Con calma',188,'Daddy Yankee','Daddy Yankee','2019-01-24','Reggaeton'),
+(3,'It''s My Life',205,'Bon Jovi','Jon Bon Jovi','2000-05-23','Pop'),
+(4,'Live is Life',242,'Opus','Opus','1985-01-01','Reggae'),
+(5,'Countdown to Extinction',249,'Megadeth','Megadeth','1992-07-14','Heavy Metal'),
+(6, 'Si nos dejan',139,'Luis Miguel','Luis Miguel','1995-10-17','Bolero');
\ No newline at end of file