diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/AppConfig.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/AppConfig.java new file mode 100644 index 0000000000..e408b77d5f --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/AppConfig.java @@ -0,0 +1,49 @@ +package com.baeldung.flush; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; + +@Configuration +public class AppConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) + .build(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { + LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); + emf.setDataSource(dataSource); + emf.setPackagesToScan("com.baeldung.flush"); + emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + emf.setJpaProperties(getHibernateProperties()); + return emf; + } + + @Bean + public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory.getObject()); + } + + private Properties getHibernateProperties() { + Properties properties = new Properties(); + properties.setProperty("hibernate.hbm2ddl.auto", "create"); + properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + return properties; + } +} + + + + diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/Customer.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/Customer.java new file mode 100644 index 0000000000..f4fc3c5b1f --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/Customer.java @@ -0,0 +1,52 @@ +package com.baeldung.flush; + +import java.util.Objects; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Customer { + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Customer customer = (Customer) o; + return age == customer.age && name.equals(customer.name); + } + + @Override + public int hashCode() { + return Objects.hash(name, age); + } + + private String name; + private int age; + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/CustomerAddress.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/CustomerAddress.java new file mode 100644 index 0000000000..eb8caef19d --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/flush/CustomerAddress.java @@ -0,0 +1,47 @@ +package com.baeldung.flush; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class CustomerAddress { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String street; + + private String city; + + private long customer_id; + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Long getId() { + return id; + } + + public long getCustomer_id() { + return customer_id; + } + + public void setCustomer_id(long customer_id) { + this.customer_id = customer_id; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/flush/FlushIntegrationTest.java b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/flush/FlushIntegrationTest.java new file mode 100644 index 0000000000..0b301532a5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/flush/FlushIntegrationTest.java @@ -0,0 +1,199 @@ +package com.baeldung.spring.data.jpa.flush; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.baeldung.flush.AppConfig; +import com.baeldung.flush.Customer; +import com.baeldung.flush.CustomerAddress; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.FlushModeType; +import jakarta.persistence.PersistenceUnit; +import jakarta.persistence.TypedQuery; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { AppConfig.class }) +public class FlushIntegrationTest { + + private static final Customer EXPECTED_CUSTOMER = aCustomer(); + + @PersistenceUnit + private EntityManagerFactory entityManagerFactory; + + private EntityManager entityManager; + + @BeforeEach + void setup() { + entityManager = entityManagerFactory.createEntityManager(); + } + + @Test + void givenANewCustomer_whenPersistAndNoFlush_thenDatabaseNotSynchronizedWithPersistentContextUsingCommitFlushMode() { + + entityManager.setFlushMode(FlushModeType.COMMIT); + + EntityTransaction transaction = getTransaction(); + Customer customer = saveCustomerInPersistentContext("Alice", 30); + Customer customerInContext = entityManager.find(Customer.class, customer.getId()); + assertDataInPersitentContext(customerInContext); + + TypedQuery retrievedCustomer = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'Alice'", Customer.class); + + List resultList = retrievedCustomer.getResultList(); + + assertThat(resultList).isEmpty(); + transaction.rollback(); + } + + @Test + void givenANewCustomer_whenPersistAndFlush_thenDatabaseSynchronizedWithPersistentContextUsingCommitFlushMode() { + entityManager.setFlushMode(FlushModeType.COMMIT); + + EntityTransaction transaction = getTransaction(); + Customer customer = saveCustomerInPersistentContext("Alice", 30); + entityManager.flush(); + Long generatedCustomerID = customer.getId(); + + Customer customerInContext = entityManager.find(Customer.class, generatedCustomerID); + assertDataInPersitentContext(customerInContext); + + TypedQuery retrievedCustomer = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'Alice'", Customer.class); + + Customer result = retrievedCustomer.getSingleResult(); + assertThat(result).isEqualTo(EXPECTED_CUSTOMER); + transaction.rollback(); + } + + @Test + public void givenANewCustomer_whenPersistAndFlush_thenCustomerIdGeneratedToBeAddedInAddress() { + entityManager.setFlushMode(FlushModeType.COMMIT); + EntityTransaction transaction = getTransaction(); + + saveCustomerInPersistentContext("John", 25); + entityManager.flush(); + + Customer retrievedCustomer = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'John'", Customer.class) + .getSingleResult(); + Long customerId = retrievedCustomer.getId(); + + CustomerAddress address = new CustomerAddress(); + address.setCustomer_id(customerId); + entityManager.persist(address); + entityManager.flush(); + + CustomerAddress customerAddress = entityManager.createQuery("SELECT a FROM CustomerAddress a WHERE a.customer_id = :customerID", CustomerAddress.class) + .setParameter("customerID", customerId) + .getSingleResult(); + + assertThat(customerAddress).isNotNull(); + transaction.rollback(); + } + + @Test + void givenANewCustomer_whenPersistAndNoFlush_thenDBIsSynchronizedWithThePersistentContextWithAutoFlushMode() { + entityManager.setFlushMode(FlushModeType.AUTO); + EntityTransaction transaction = getTransaction(); + + Customer customer = saveCustomerInPersistentContext("Alice", 30); + Customer customerInContext = entityManager.find(Customer.class, customer.getId()); + assertDataInPersitentContext(customerInContext); + + TypedQuery retrievedCustomer = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'Alice'", Customer.class); + + Customer result = retrievedCustomer.getSingleResult(); + + assertThat(result).isEqualTo(EXPECTED_CUSTOMER); + + transaction.rollback(); + } + + @Test + public void givenFlushModeAutoAndNewCustomer_whenPersistAndNoFlush_thenCustomerIdGeneratedToBeAddedInAddress() { + entityManager.setFlushMode(FlushModeType.AUTO); + EntityTransaction transaction = getTransaction(); + + saveCustomerInPersistentContext("John", 25); + + Customer singleResult = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'John'", Customer.class) + .getSingleResult(); + Long customerId = singleResult.getId(); + + CustomerAddress address = new CustomerAddress(); + address.setCustomer_id(customerId); + entityManager.persist(address); + + CustomerAddress customerAddress = entityManager.createQuery("SELECT a FROM CustomerAddress a WHERE a.customer_id = :customerID", CustomerAddress.class) + .setParameter("customerID", customerId) + .getSingleResult(); + + assertThat(customerAddress).isNotNull(); + transaction.rollback(); + } + + @Test + public void givenFlushModeAutoAndNewCustomer_whenPersistAndFlush_thenCustomerIdGeneratedToBeAddedInAddress() { + entityManager.setFlushMode(FlushModeType.AUTO); + EntityTransaction transaction = getTransaction(); + + saveCustomerInPersistentContext("John", 25); + + Customer singleResult = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = 'John'", Customer.class) + .getSingleResult(); + Long customerId = singleResult.getId(); + + CustomerAddress address = new CustomerAddress(); + address.setCustomer_id(customerId); + entityManager.persist(address); + entityManager.flush(); + + CustomerAddress customerAddress = entityManager.createQuery("SELECT a FROM CustomerAddress a WHERE a.customer_id = :customerID", CustomerAddress.class) + .setParameter("customerID", customerId) + .getSingleResult(); + + assertThat(customerAddress).isNotNull(); + + transaction.rollback(); + } + + private static void assertDataInPersitentContext(Customer customerInContext) { + assertThat(customerInContext).isNotNull(); + assertThat(customerInContext.getName()).isEqualTo("Alice"); + } + + private Customer saveCustomerInPersistentContext(String name, int age) { + Customer customer = new Customer(); + customer.setName(name); + customer.setAge(age); + entityManager.persist(customer); + return customer; + } + + @AfterEach + public void cleanup() { + entityManager.clear(); + } + + private static Customer aCustomer() { + Customer customer = new Customer(); + customer.setName("Alice"); + customer.setAge(30); + return customer; + } + + private EntityTransaction getTransaction() { + EntityTransaction transaction = entityManager.getTransaction(); + transaction.begin(); + return transaction; + } +} \ No newline at end of file