From 35bdac1c59739c4d59f16e822add3a8482d38344 Mon Sep 17 00:00:00 2001 From: Zeeshan Arif Date: Sun, 31 Mar 2024 17:49:06 +0500 Subject: [PATCH] BAEL-7692 --- .../spring/data/jpa/joinquery/AppConfig.java | 52 ++++++++ .../data/jpa/joinquery/DTO/ResultDTO.java | 119 ++++++++++++++++++ .../data/jpa/joinquery/entities/Customer.java | 104 +++++++++++++++ .../jpa/joinquery/entities/CustomerOrder.java | 88 +++++++++++++ .../data/jpa/joinquery/entities/Product.java | 84 +++++++++++++ .../repositories/CustomerRepository.java | 9 ++ .../repositories/JoinRepository.java | 26 ++++ .../jpa/joinquery/JoinRepositoryTest.java | 98 +++++++++++++++ 8 files changed, 580 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java create mode 100644 persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryTest.java diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java new file mode 100644 index 0000000000..840d26edf7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/AppConfig.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.data.jpa.joinquery; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +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; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableAutoConfiguration +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.spring.data.jpa.joinquery.entities" + , "com.baeldung.spring.data.jpa.joinquery.DTO" + , "com.baeldung.spring.data.jpa.joinquery.repositories"); + 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/spring/data/jpa/joinquery/DTO/ResultDTO.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java new file mode 100644 index 0000000000..9464c25ce8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/DTO/ResultDTO.java @@ -0,0 +1,119 @@ +package com.baeldung.spring.data.jpa.joinquery.DTO; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import org.springframework.context.annotation.Bean; + +import java.time.LocalDate; + +class DTO { + private Long customer_id; + private Long order_id; + private Long product_id; + + public DTO(Long customer_id, Long order_id, Long product_id) { + this.customer_id = customer_id; + this.order_id = order_id; + this.product_id = product_id; + } +} + +@Entity +@IdClass(DTO.class) +public class ResultDTO { + @Id + private Long customer_id; + + @Id + private Long order_id; + + @Id + private Long product_id; + + public void setCustomer_id(Long customer_id) { + this.customer_id = customer_id; + } + + public Long getProduct_id() { + return product_id; + } + + public void setProduct_id(Long product_id) { + this.product_id = product_id; + } + + public ResultDTO(Long customer_id, Long order_id, Long product_id, String customerName, String customerEmail, LocalDate orderDate, String productName, Double productPrice) { + this.customer_id = customer_id; + this.order_id = order_id; + this.product_id = product_id; + this.customerName = customerName; + this.customerEmail = customerEmail; + this.orderDate = orderDate; + this.productName = productName; + this.productPrice = productPrice; + } + + private String customerName; + private String customerEmail; + private LocalDate orderDate; + private String productName; + private Double productPrice; + + public Long getCustomer_id() { + return customer_id; + } + + public void setCustoemr_id(Long custoemr_id) { + this.customer_id = custoemr_id; + } + + public String getCustomerName() { + return customerName; + } + + public void setCustomerName(String customerName) { + this.customerName = customerName; + } + + public String getCustomerEmail() { + return customerEmail; + } + + public void setCustomerEmail(String customerEmail) { + this.customerEmail = customerEmail; + } + + public Long getOrder_id() { + return order_id; + } + + public void setOrder_id(Long order_id) { + this.order_id = order_id; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Double getProductPrice() { + return productPrice; + } + + public void setProductPrice(Double productPrice) { + this.productPrice = productPrice; + } + +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java new file mode 100644 index 0000000000..8da7aa21a2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Customer.java @@ -0,0 +1,104 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Set; + +@Entity +public class Customer { + public Customer(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToMany(mappedBy = "customer" + , cascade = CascadeType.ALL) + private Set customerOrders; + + public Customer(Long id, Set customerOrders, String email, LocalDate dob, String name) { + this.id = id; + this.customerOrders = customerOrders; + this.email = email; + this.dob = dob; + this.name = name; + } + + public void setId(Long id) { + this.id = id; + } + + public void setCustomerOrders(Set customerOrders) { + this.customerOrders = customerOrders; + } + + @Override + public String toString() { + return "Patient{" + + "id=" + id + + ", orders=" + customerOrders + + ", email='" + email + '\'' + + ", dob=" + dob + + ", name='" + name + '\'' + + '}'; + } + + public Set getOrders() { + return customerOrders; + } + + public void setOrders(Set orders) { + this.customerOrders = orders; + } + + @Column + private String email; + + @Column(name = "dob", columnDefinition = "DATE") + private LocalDate dob; + + @Column + private String name; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Customer patient = (Customer) o; + return Objects.equals(id, patient.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public Long getId() { + return id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public LocalDate getDob() { + return dob; + } + + public void setDob(LocalDate dob) { + this.dob = dob; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java new file mode 100644 index 0000000000..d147543e2f --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/CustomerOrder.java @@ -0,0 +1,88 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Set; + +@Entity +public class CustomerOrder { + public CustomerOrder(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public void setId(Long id) { + this.id = id; + } + + public Set getProducts() { + return products; + } + + public void setProducts(Set products) { + this.products = products; + } + + @OneToMany(mappedBy = "customerOrder" + , cascade = CascadeType.ALL) + private Set products; + + @Column + private LocalDate orderDate; + + public CustomerOrder(Long id, Set products, LocalDate orderDate, Customer customer) { + this.id = id; + this.products = products; + this.orderDate = orderDate; + this.customer = customer; + } + + @Override + public String toString() { + return "Consult{" + + "id=" + id + + ", products=" + products + + ", orderDate=" + orderDate + + ", customer=" + customer + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomerOrder co = (CustomerOrder) o; + return Objects.equals(id, co.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="customer_id", nullable = false) + private Customer customer; + + public Long getId() { + return id; + } + + public LocalDate getOrderDate() { + return orderDate; + } + + public void setOrderDate(LocalDate orderDate) { + this.orderDate = orderDate; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(Customer customer) { + this.customer = customer; + } +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java new file mode 100644 index 0000000000..ea18e6225e --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/entities/Product.java @@ -0,0 +1,84 @@ +package com.baeldung.spring.data.jpa.joinquery.entities; + +import jakarta.persistence.*; + +import java.util.Objects; + +@Entity +public class Product { + public Product(){} + @Id + //@GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + public Product(Long id, String productName, Double price, CustomerOrder customerOrder) { + this.id = id; + this.productName = productName; + this.price = price; + this.customerOrder = customerOrder; + } + + @Column + private String productName; + + @Column + private Double price; + + @Override + public String toString() { + return "Dispense{" + + "id=" + id + + ", productName='" + productName + '\'' + + ", price=" + price + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Product dispense = (Product) o; + return Objects.equals(id, dispense.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public CustomerOrder getCustomerOrder() { + return customerOrder; + } + + public void setCustomerOrder(CustomerOrder co) { + this.customerOrder = co; + } + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="customerorder_id", nullable = false) + private CustomerOrder customerOrder; +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java new file mode 100644 index 0000000000..ba7ece74b8 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/CustomerRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.data.jpa.joinquery.repositories; + +import com.baeldung.spring.data.jpa.joinquery.entities.Customer; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CustomerRepository extends CrudRepository { +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java new file mode 100644 index 0000000000..8630d44f86 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/spring/data/jpa/joinquery/repositories/JoinRepository.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.data.jpa.joinquery.repositories; + +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Map; + +@Repository +public interface JoinRepository extends CrudRepository { + @Query(value = "SELECT new com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO(c.id, o.id, p.id, c.name, c.email, o.orderDate, p.productName, p.price) " + + " from Customer c, CustomerOrder o ,Product p " + + " where c.id=o.customer.id " + + " and o.id=p.customerOrder.id " + + " and c.id=?1 ") + List findResultDTOByCustomer(Long id); + + @Query(value = "SELECT c.*, o.*, p.* " + + " from Customer c, CustomerOrder o ,Product p " + + " where c.id=o.customer_id " + + " and o.id=p.customerOrder_id " + + " and c.id=?1 " + , nativeQuery = true) + List> findByCustomer(Long id); +} diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryTest.java b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryTest.java new file mode 100644 index 0000000000..b5cf78d5e1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/spring/data/jpa/joinquery/JoinRepositoryTest.java @@ -0,0 +1,98 @@ +package com.baeldung.spring.data.jpa.joinquery; + +import com.baeldung.spring.data.jpa.joinquery.entities.Customer; +import com.baeldung.spring.data.jpa.joinquery.entities.CustomerOrder; +import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO; +import com.baeldung.spring.data.jpa.joinquery.entities.Product; +import com.baeldung.spring.data.jpa.joinquery.repositories.CustomerRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import jakarta.persistence.PersistenceUnit; +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.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.baeldung.spring.data.jpa.joinquery.repositories.JoinRepository; +import java.time.LocalDate; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { AppConfig.class }) +class JoinRepositoryTest { + + @Autowired + JoinRepository joinRepository; + + @Autowired + CustomerRepository customerRepository; + + @PersistenceUnit + EntityManagerFactory entityManagerFactory; + + EntityManager entityManager; + + @BeforeEach + void setUp() { + customerRepository.deleteAll(); + entityManager = entityManagerFactory.createEntityManager(); + Customer c = new Customer(1L, null, "email1@email.com", LocalDate.now(), "Customer"); + CustomerOrder o1 = new CustomerOrder(1L, null, LocalDate.now(), c); + CustomerOrder o2 = new CustomerOrder(2L, null, LocalDate.of(2024,1,1), c); + + Product p1 = new Product(1L,"Product1", 25.20, o1); + Product p2 = new Product(2L, "Product2", 26.20, o1); + Product p3 = new Product(3L, "Product3", 27.20, o2); + + Set cos01 = new HashSet<>(); + cos01.add(o1); + cos01.add(o2); + Set productsO1 = new HashSet<>(); + productsO1.add(p1); + productsO1.add(p2); + Set productsO2 = new HashSet<>(); + productsO1.add(p3); + + c.setCustomerOrders(cos01); + o1.setProducts(productsO1); + o2.setProducts(productsO2); + + EntityTransaction et = getTransaction(); + entityManager.persist(c); + entityManager.flush(); + et.commit(); + } + + @AfterEach + void tearDown() { + } + + @Test + void whenFindResultDTOByCustomer_thenReturnResultDTO() { + List resultDTO = joinRepository.findResultDTOByCustomer(1L); + assertInstanceOf(ResultDTO.class, resultDTO.get(0)); + } + + @Test + void whenFindByCustomerNativeQuery_thenReturnMapsForObjects() { + List> res = joinRepository.findByCustomer(1L); + //the map objects in the res List has 9 String keys aka 9 columns corresponding to the columns of customer, customerOrder, product + res.forEach(map -> { + assertEquals(9, map.keySet().size()); + }); + } + private EntityTransaction getTransaction() { + EntityTransaction transaction = entityManager.getTransaction(); + transaction.begin(); + return transaction; + } +} \ No newline at end of file