From e0a7591f9defa207018816003a8b99e192a9b5fe Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Sun, 19 Jun 2022 16:32:10 -0300 Subject: [PATCH] first draft --- .../SpringBootUniqueFieldApplication.java | 15 +++ .../unique/field/dao/AssetRepository.java | 8 ++ .../unique/field/dao/CompanyRepository.java | 11 ++ .../unique/field/dao/Customer2Repository.java | 8 ++ .../unique/field/dao/CustomerRepository.java | 11 ++ .../boot/unique/field/dao/SaleRepository.java | 12 ++ .../boot/unique/field/data/Asset.java | 29 +++++ .../boot/unique/field/data/Company.java | 40 +++++++ .../boot/unique/field/data/Customer.java | 57 +++++++++ .../boot/unique/field/data/Customer2.java | 47 ++++++++ .../baeldung/boot/unique/field/data/Sale.java | 36 ++++++ .../boot/unique/field/data/SaleId.java | 22 ++++ .../field/web/UniqueFieldController.java | 93 +++++++++++++++ .../boot.unique.field/app.properties | 1 + .../field/UniqueFieldIntegrationTest.java | 112 ++++++++++++++++++ 15 files changed, 502 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/SpringBootUniqueFieldApplication.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/AssetRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CompanyRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CustomerRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/SaleRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Asset.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Company.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Sale.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/SaleId.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/web/UniqueFieldController.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.unique.field/app.properties create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/unique/field/UniqueFieldIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/SpringBootUniqueFieldApplication.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/SpringBootUniqueFieldApplication.java new file mode 100644 index 0000000000..648ecd4dfb --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/SpringBootUniqueFieldApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.boot.unique.field; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@SpringBootApplication +@PropertySource("classpath:boot.unique.field/app.properties") +@EnableMongoRepositories(basePackages = { "com.baeldung.boot.unique.field" }) +public class SpringBootUniqueFieldApplication { + public static void main(String... args) { + SpringApplication.run(SpringBootUniqueFieldApplication.class, args); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/AssetRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/AssetRepository.java new file mode 100644 index 0000000000..9adca8b4bd --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/AssetRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.unique.field.dao; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.unique.field.data.Asset; + +public interface AssetRepository extends MongoRepository { +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CompanyRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CompanyRepository.java new file mode 100644 index 0000000000..718e284efe --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CompanyRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.boot.unique.field.dao; + +import java.util.Optional; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.unique.field.data.Company; + +public interface CompanyRepository extends MongoRepository { + Optional findByEmail(String email); +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java new file mode 100644 index 0000000000..6afe004609 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.unique.field.dao; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.unique.field.data.Customer2; + +public interface Customer2Repository extends MongoRepository { +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CustomerRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CustomerRepository.java new file mode 100644 index 0000000000..f6e5b54470 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/CustomerRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.boot.unique.field.dao; + +import java.util.Optional; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.unique.field.data.Customer; + +public interface CustomerRepository extends MongoRepository { + Optional findByStoreIdAndNumber(Long storeId, Long number); +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/SaleRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/SaleRepository.java new file mode 100644 index 0000000000..8547a5ab76 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/SaleRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.boot.unique.field.dao; + +import java.util.Optional; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.unique.field.data.Sale; +import com.baeldung.boot.unique.field.data.SaleId; + +public interface SaleRepository extends MongoRepository { + Optional findBySaleId(SaleId id); +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Asset.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Asset.java new file mode 100644 index 0000000000..9652691a8b --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Asset.java @@ -0,0 +1,29 @@ +package com.baeldung.boot.unique.field.data; + +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Asset { + @Indexed(unique = true) + private String name; + + @Indexed(unique = true) + private Integer number; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Company.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Company.java new file mode 100644 index 0000000000..31b4cf0588 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Company.java @@ -0,0 +1,40 @@ +package com.baeldung.boot.unique.field.data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Company { + @Id + private String id; + + private String name; + + @Indexed(unique = true) + private String email; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer.java new file mode 100644 index 0000000000..d1459dc663 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer.java @@ -0,0 +1,57 @@ +package com.baeldung.boot.unique.field.data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@CompoundIndex(name = "customer_idx", def = "{ 'storeId': 1, 'number': 1 }", unique = true) +public class Customer { + @Id + private String id; + + private Long storeId; + + private Long number; + + private String name; + + public Customer() { + } + + public Customer(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number = number; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java new file mode 100644 index 0000000000..523a0a9841 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java @@ -0,0 +1,47 @@ +package com.baeldung.boot.unique.field.data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.index.CompoundIndex; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@CompoundIndex(def = "{ 'storeId': 1, 'number': 1 }", unique = true) +public class Customer2 { + @Id + private Long storeId; + + private Long number; + + private String name; + + public Customer2() { + } + + public Customer2(String name) { + this.name = name; + } + + public Long getStoreId() { + return storeId; + } + + public void setStoreId(Long storeId) { + this.storeId = storeId; + } + + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number = number; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Sale.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Sale.java new file mode 100644 index 0000000000..3d0a549575 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Sale.java @@ -0,0 +1,36 @@ +package com.baeldung.boot.unique.field.data; + +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Sale { + @Indexed(unique = true) + private SaleId saleId; + + private Double value; + + public Sale() { + } + + public Sale(SaleId saleId) { + super(); + this.saleId = saleId; + } + + public SaleId getSaleId() { + return saleId; + } + + public void setSaleId(SaleId saleId) { + this.saleId = saleId; + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + this.value = value; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/SaleId.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/SaleId.java new file mode 100644 index 0000000000..69a5c5a561 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/SaleId.java @@ -0,0 +1,22 @@ +package com.baeldung.boot.unique.field.data; + +public class SaleId { + private Long item; + private String date; + + public Long getItem() { + return item; + } + + public void setItem(Long item) { + this.item = item; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/web/UniqueFieldController.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/web/UniqueFieldController.java new file mode 100644 index 0000000000..8ac00c497f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/web/UniqueFieldController.java @@ -0,0 +1,93 @@ +package com.baeldung.boot.unique.field.web; + +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.boot.unique.field.dao.AssetRepository; +import com.baeldung.boot.unique.field.dao.CompanyRepository; +import com.baeldung.boot.unique.field.dao.Customer2Repository; +import com.baeldung.boot.unique.field.dao.CustomerRepository; +import com.baeldung.boot.unique.field.dao.SaleRepository; +import com.baeldung.boot.unique.field.data.Asset; +import com.baeldung.boot.unique.field.data.Company; +import com.baeldung.boot.unique.field.data.Customer; +import com.baeldung.boot.unique.field.data.Customer2; +import com.baeldung.boot.unique.field.data.Sale; +import com.baeldung.boot.unique.field.data.SaleId; + +@RestController +@RequestMapping("/unique-field") +public class UniqueFieldController { + @Autowired + private SaleRepository saleRepo; + + @Autowired + private CompanyRepository companyRepo; + + @Autowired + private CustomerRepository customerRepo; + + @Autowired + private Customer2Repository customer2Repo; + + @Autowired + private AssetRepository assetRepo; + + @PostMapping("/sale") + public Sale post(@RequestBody Sale sale) { + return saleRepo.insert(sale); + } + + @GetMapping("/sale") + public Optional getSale(SaleId id) { + return saleRepo.findBySaleId(id); + } + + @PostMapping("/company") + public Company post(@RequestBody Company company) { + return companyRepo.insert(company); + } + + @PutMapping("/company") + public Company put(@RequestBody Company company) { + return companyRepo.save(company); + } + + @GetMapping("/company/{id}") + public Optional getCompany(@PathVariable String id) { + return companyRepo.findById(id); + } + + @PostMapping("/customer") + public Customer post(@RequestBody Customer customer) { + return customerRepo.insert(customer); + } + + @PostMapping("/customer2") + public Customer2 post(@RequestBody Customer2 customer) { + return customer2Repo.insert(customer); + } + + @GetMapping("/customer/{id}") + public Optional getCustomer(@PathVariable String id) { + return customerRepo.findById(id); + } + + @PostMapping("/asset") + public Asset post(@RequestBody Asset asset) { + return assetRepo.insert(asset); + } + + @GetMapping("/asset/{id}") + public Optional getAsset(@PathVariable String id) { + return assetRepo.findById(id); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.unique.field/app.properties b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.unique.field/app.properties new file mode 100644 index 0000000000..a73a94d850 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.unique.field/app.properties @@ -0,0 +1 @@ +spring.data.mongodb.auto-index-creation=true diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/unique/field/UniqueFieldIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/unique/field/UniqueFieldIntegrationTest.java new file mode 100644 index 0000000000..c18a877b79 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/unique/field/UniqueFieldIntegrationTest.java @@ -0,0 +1,112 @@ +package com.baeldung.boot.unique.field; + +import static org.junit.Assert.assertThrows; + +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.dao.DuplicateKeyException; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.boot.unique.field.dao.AssetRepository; +import com.baeldung.boot.unique.field.dao.CompanyRepository; +import com.baeldung.boot.unique.field.dao.CustomerRepository; +import com.baeldung.boot.unique.field.dao.SaleRepository; +import com.baeldung.boot.unique.field.data.Asset; +import com.baeldung.boot.unique.field.data.Company; +import com.baeldung.boot.unique.field.data.Customer; +import com.baeldung.boot.unique.field.data.Sale; +import com.baeldung.boot.unique.field.data.SaleId; + +@SpringBootTest +@DirtiesContext +@RunWith(SpringRunner.class) +public class UniqueFieldIntegrationTest { + @Autowired + private SaleRepository saleRepo; + + @Autowired + private CompanyRepository companyRepo; + + @Autowired + private CustomerRepository customerRepo; + + @Autowired + private AssetRepository assetRepo; + + @Test + public void givenMultipleIndexes_whenAnyFieldDupe_thenExceptionIsThrown() { + Asset a = new Asset(); + a.setName("Name"); + a.setNumber(1); + + assetRepo.insert(a); + + Asset b = new Asset(); + b.setName("Name"); + b.setNumber(2); + assertThrows(DuplicateKeyException.class, () -> { + assetRepo.insert(b); + }); + + Asset c = new Asset(); + c.setName("Other"); + c.setNumber(1); + assertThrows(DuplicateKeyException.class, () -> { + assetRepo.insert(c); + }); + } + + @Test + public void givenUniqueIndex_whenInsertingDupe_thenExceptionIsThrown() { + Company a = new Company(); + a.setName("Name"); + a.setEmail("a@mail.com"); + + companyRepo.insert(a); + + Company b = new Company(); + b.setName("Other"); + b.setEmail("a@mail.com"); + assertThrows(DuplicateKeyException.class, () -> { + companyRepo.insert(b); + }); + } + + @Test + public void givenCompoundIndex_whenDupeInsert_thenExceptionIsThrown() { + Customer customerA = new Customer("Name A"); + customerA.setNumber(1l); + customerA.setStoreId(2l); + + Customer customerB = new Customer("Name B"); + customerB.setNumber(1l); + customerB.setStoreId(2l); + + customerRepo.insert(customerA); + + assertThrows(DuplicateKeyException.class, () -> { + customerRepo.insert(customerB); + }); + } + + @Test + public void givenCustomTypeIndex_whenInsertingDupe_thenExceptionIsThrown() { + SaleId id = new SaleId(); + id.setDate("2022-06-15"); + id.setItem(1L); + + Sale a = new Sale(id); + a.setValue(53.94); + + saleRepo.insert(a); + + Sale b = new Sale(id); + b.setValue(100.00); + assertThrows(DuplicateKeyException.class, () -> { + saleRepo.insert(b); + }); + } +}