diff --git a/persistence-modules/hibernate-jpa-3/pom.xml b/persistence-modules/hibernate-jpa-3/pom.xml
index 4de550c3e7cc..22f5a6d27b6f 100644
--- a/persistence-modules/hibernate-jpa-3/pom.xml
+++ b/persistence-modules/hibernate-jpa-3/pom.xml
@@ -62,7 +62,11 @@
3.0.4
2.1.214
3.9.1
- 3.2.0
+
+ 3.1.0
diff --git a/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/DirtyCheckingApplication.java b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/DirtyCheckingApplication.java
new file mode 100644
index 000000000000..e318c97b7ab4
--- /dev/null
+++ b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/DirtyCheckingApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.hibernate.dirtychecking;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DirtyCheckingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(DirtyCheckingApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/entity/Product.java b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/entity/Product.java
new file mode 100644
index 000000000000..4f0ba380b452
--- /dev/null
+++ b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/entity/Product.java
@@ -0,0 +1,48 @@
+package com.baeldung.hibernate.dirtychecking.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+
+@Entity
+public class Product {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String code;
+ private double price;
+
+ public Product() {
+ }
+
+ public Product(String code, double price) {
+ this.code = code;
+ this.price = price;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ }
+}
diff --git a/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/repository/ProductRepository.java b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/repository/ProductRepository.java
new file mode 100644
index 000000000000..a9e47965d9a0
--- /dev/null
+++ b/persistence-modules/hibernate-jpa-3/src/main/java/com/baeldung/hibernate/dirtychecking/repository/ProductRepository.java
@@ -0,0 +1,13 @@
+package com.baeldung.hibernate.dirtychecking.repository;
+
+import java.util.Optional;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.hibernate.dirtychecking.entity.Product;
+
+@Repository
+public interface ProductRepository extends JpaRepository {
+ Optional findByCode(String code);
+}
diff --git a/persistence-modules/hibernate-jpa-3/src/main/resources/application-dirtychecking.yml b/persistence-modules/hibernate-jpa-3/src/main/resources/application-dirtychecking.yml
new file mode 100644
index 000000000000..5e86f412eb69
--- /dev/null
+++ b/persistence-modules/hibernate-jpa-3/src/main/resources/application-dirtychecking.yml
@@ -0,0 +1,3 @@
+spring:
+ jpa:
+ show-sql: true
\ No newline at end of file
diff --git a/persistence-modules/hibernate-jpa-3/src/test/java/com/baeldung/hibernate/dirtychecking/ProductRepositoryTest.java b/persistence-modules/hibernate-jpa-3/src/test/java/com/baeldung/hibernate/dirtychecking/ProductRepositoryTest.java
new file mode 100644
index 000000000000..c63dcd9d66e9
--- /dev/null
+++ b/persistence-modules/hibernate-jpa-3/src/test/java/com/baeldung/hibernate/dirtychecking/ProductRepositoryTest.java
@@ -0,0 +1,55 @@
+package com.baeldung.hibernate.dirtychecking;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.hibernate.dirtychecking.entity.Product;
+import com.baeldung.hibernate.dirtychecking.repository.ProductRepository;
+
+import jakarta.persistence.EntityManager;
+
+@SpringBootTest
+@ActiveProfiles("dirtychecking")
+public class ProductRepositoryTest {
+
+ @Autowired
+ private ProductRepository productRepository;
+
+ @Autowired
+ private EntityManager entityManager;
+
+ @Test
+ @Transactional
+ void givenProduct_whenModifiedWithoutSave_thenAssertChangesPersisted() {
+ Product product = new Product("LOREM", 100.00);
+ productRepository.save(product);
+
+ product.setPrice(80.00);
+ entityManager.flush();
+ entityManager.clear();
+
+ Product updatedProduct = productRepository.findByCode("LOREM").orElseThrow(RuntimeException::new);
+ assertEquals(80.00, updatedProduct.getPrice());
+ }
+
+ @Test
+ @Transactional
+ void givenDetachedProduct_whenModifiedWithoutSave_thenAssertChangesNotPersisted() {
+ Product product = new Product("LOREM", 100.00);
+ productRepository.save(product);
+
+ entityManager.detach(product);
+ product.setPrice(80.00);
+ entityManager.flush();
+ entityManager.clear();
+
+ Product updatedProduct = productRepository.findByCode("LOREM").orElseThrow(RuntimeException::new);
+ assertEquals(100.00, updatedProduct.getPrice());
+ }
+
+}