BAEL-7572: Spring Data JPA Repository for Database View (#15918)

This commit is contained in:
Manfred 2024-02-28 02:13:46 +00:00 committed by GitHub
parent 7039de679d
commit 6d1ed25da1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 334 additions and 0 deletions

View File

@ -0,0 +1,13 @@
package com.baeldung.dbview;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DatabaseViewApplication {
public static void main(String[] args) {
SpringApplication.run(DatabaseViewApplication.class, args);
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.dbview;
import jakarta.persistence.AttributeOverride;
import jakarta.persistence.AttributeOverrides;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
@Entity
@Table(name = "SHOP_SALE_VIEW")
@Getter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = {"id"})
public class ShopSale {
@EmbeddedId
@AttributeOverrides({
@AttributeOverride( name = "shopId", column = @Column(name = "shop_id")),
@AttributeOverride( name = "year", column = @Column(name = "transaction_year")),
@AttributeOverride( name = "month", column = @Column(name = "transaction_month"))
})
private ShopSaleCompositeId id;
@Column(name = "shop_location", length = 100)
private String shopLocation;
@Column(name = "total_amount")
private BigDecimal totalAmount;
}

View File

@ -0,0 +1,24 @@
package com.baeldung.dbview;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Getter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class ShopSaleCompositeId {
private int shopId;
private int year;
private int month;
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dbview;
import java.util.List;
public interface ShopSaleRepository extends ViewRepository<ShopSale, ShopSaleCompositeId> {
List<ShopSale> findByIdShopId(Integer shopId);
}

View File

@ -0,0 +1,46 @@
package com.baeldung.dbview;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
@Entity
@Table(name = "SHOP_SALE_VIEW")
@Getter
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = {"id"})
public class ShopSaleVid {
@Id
@Column(name = "id")
private Long id;
@Column(name = "shop_id")
private int shopId;
@Column(name = "shop_location", length = 100)
private String shopLocation;
@Column(name = "transaction_year")
private int year;
@Column(name = "transaction_month")
private int month;
@Column(name = "total_amount")
private BigDecimal totalAmount;
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dbview;
import java.util.List;
public interface ShopSaleVidRepository extends ViewNoIdRepository<ShopSaleVid, Long> {
List<ShopSaleVid> findByShopId(Integer shopId);
}

View File

@ -0,0 +1,15 @@
package com.baeldung.dbview;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
import java.util.List;
@NoRepositoryBean
public interface ViewNoIdRepository<T, K> extends Repository<T, K> {
long count();
List<T> findAll();
}

View File

@ -0,0 +1,22 @@
package com.baeldung.dbview;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
@NoRepositoryBean
public interface ViewRepository<T, K> extends Repository<T, K> {
long count();
boolean existsById(K id);
List<T> findAll();
List<T> findAllById(Iterable<K> ids);
Optional<T> findById(K id);
}

View File

@ -0,0 +1,65 @@
package com.baeldung.dbview;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = DatabaseViewApplication.class, properties = {
"spring.jpa.show-sql=true",
"spring.jpa.properties.hibernate.format_sql=true",
"spring.jpa.hibernate.ddl-auto=none",
"spring.jpa.defer-datasource-initialization=true",
"spring.sql.init.data-locations=classpath:shop-sale-data.sql"
})
class ShopSaleRepositoryIntegrationTest {
private static final ShopSaleCompositeId id = ShopSaleCompositeId.builder()
.shopId(1)
.year(2024)
.month(1)
.build();
@Autowired
private ShopSaleRepository shopSaleRepository;
@Test
void whenCount_thenValueGreaterThanOne() {
assertThat(shopSaleRepository.count()).isGreaterThan(0);
}
@Test
void whenFindAll_thenReturnAllRecords() {
assertThat(shopSaleRepository.findAll()).isNotEmpty();
}
@Test
void whenExistsById_thenReturnTrue() {
assertThat(shopSaleRepository.existsById(id)).isTrue();
}
@Test
void whenFindAllById_thenReturnListWithTwoInstances() {
assertThat(shopSaleRepository.findAllById(List.of (id))).hasSize(1);
}
@Test
void whenFindById_thenReturnAnInstance() {
assertThat(shopSaleRepository.findById(id).isPresent()).isTrue();
}
@Test
void whenFindByShopId_thenReturnAllShopSaleOfThatShop() {
var shopId = 1;
List<ShopSale> shopSaleVidList = shopSaleRepository.findByIdShopId(shopId);
assertThat(shopSaleVidList).isNotEmpty();
shopSaleVidList.forEach(s -> assertThat(s.getId().getShopId()).isEqualTo(shopId));
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.dbview;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(classes = DatabaseViewApplication.class, properties = {
"spring.jpa.show-sql=true",
"spring.jpa.properties.hibernate.format_sql=true",
"spring.jpa.hibernate.ddl-auto=none",
"spring.jpa.defer-datasource-initialization=true",
"spring.sql.init.data-locations=classpath:shop-sale-data.sql"
})
class ShopSaleVidRepositoryIntegrationTest {
@Autowired
private ShopSaleVidRepository shopSaleVidRepository;
@Test
void whenCount_thenValueGreaterThanOne() {
assertThat(shopSaleVidRepository.count()).isGreaterThan(0);
}
@Test
void whenFindAll_thenReturnAllRecords() {
assertThat(shopSaleVidRepository.findAll()).isNotEmpty();
}
@Test
void whenFindByShopId_thenReturnAllShopSaleOfThatShop() {
var shopId = 1;
List<ShopSaleVid> shopSaleList = shopSaleVidRepository.findByShopId(shopId);
assertThat(shopSaleList).isNotEmpty();
shopSaleList.forEach(s -> assertThat(s.getShopId()).isEqualTo(shopId));
}
}

View File

@ -0,0 +1,47 @@
CREATE TABLE SHOP
(
shop_id int AUTO_INCREMENT,
shop_location varchar(100) NOT NULL UNIQUE,
PRIMARY KEY(shop_id)
);
CREATE TABLE SHOP_TRANSACTION
(
transaction_id bigint AUTO_INCREMENT,
transaction_date date NOT NULL,
shop_id int NOT NULL,
amount decimal(8,2) NOT NULL,
PRIMARY KEY(transaction_id),
FOREIGN KEY(shop_id) REFERENCES SHOP(shop_id)
);
CREATE VIEW SHOP_SALE_VIEW AS
SELECT ROW_NUMBER() OVER () AS id, shop_id, shop_location, transaction_year, transaction_month, SUM(amount) AS total_amount
FROM (
SELECT shop.shop_id, shop.shop_location, trans.amount, YEAR(transaction_date) AS transaction_year, MONTH(transaction_date) AS transaction_month
FROM SHOP shop, SHOP_TRANSACTION trans
WHERE shop.shop_id = trans.shop_id
) SHOP_MONTH_TRANSACTION
GROUP BY shop_id, transaction_year, transaction_month;
INSERT INTO SHOP(shop_location) VALUES ('Ealing');
INSERT INTO SHOP(shop_location) VALUES ('Richmond');
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-01-05', 1, 3.49);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-01-31', 1, 7.29);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-02-09', 1, 1.60);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-02-17', 1, 5.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-02-18', 1, 5.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-03-01', 1, 8.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-03-22', 1, 5.49);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-01-15', 2, 8.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-01-18', 2, 8.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-02-01', 2, 5.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-02-05', 2, 2.50);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-03-01', 2, 5.99);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-03-02', 2, 6.60);
INSERT INTO SHOP_TRANSACTION(transaction_date, shop_id, amount) VALUES ('2024-03-17', 2, 1.19);