From fc2cf54d9fcba29076bdc40423066118fe9db238 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Fri, 27 May 2022 23:55:58 -0300 Subject: [PATCH 1/7] BAEL-5370 - MongoDB Composite Key First Draft. --- .../SpringBootCompositeKeyApplication.java | 15 ++ .../composite/key/dao/CustomerRepository.java | 12 ++ .../composite/key/dao/SaleRepository.java | 12 ++ .../composite/key/dao/TicketRepository.java | 10 ++ .../boot/composite/key/data/Customer.java | 49 ++++++ .../boot/composite/key/data/Sale.java | 38 +++++ .../boot/composite/key/data/Ticket.java | 31 ++++ .../boot/composite/key/data/TicketId.java | 56 +++++++ .../key/service/CustomerService.java | 66 +++++++++ .../composite/key/web/CustomerController.java | 88 +++++++++++ .../boot.composite.key/app.properties | 1 + .../key/CustomerServiceIntegrationTest.java | 140 ++++++++++++++++++ 12 files changed, 518 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/TicketRepository.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/TicketId.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties create mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java new file mode 100644 index 000000000000..e9f8eab1dd50 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.boot.composite.key; + +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.composite.key/app.properties") +@EnableMongoRepositories(basePackages = { "com.baeldung.boot.composite.key" }) +public class SpringBootCompositeKeyApplication { + public static void main(String... args) { + SpringApplication.run(SpringBootCompositeKeyApplication.class, args); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java new file mode 100644 index 000000000000..6953a21ddd5e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.boot.composite.key.dao; + +import java.util.Optional; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.composite.key.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/composite/key/dao/SaleRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java new file mode 100644 index 000000000000..3caa33d4658e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.boot.composite.key.dao; + +import java.util.Optional; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.composite.key.data.Sale; +import com.baeldung.boot.composite.key.data.TicketId; + +public interface SaleRepository extends MongoRepository { + Optional findByTicketId(TicketId ticketId); +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/TicketRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/TicketRepository.java new file mode 100644 index 000000000000..b02ea461d2bb --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/TicketRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.boot.composite.key.dao; + +import org.springframework.data.mongodb.repository.MongoRepository; + +import com.baeldung.boot.composite.key.data.Ticket; +import com.baeldung.boot.composite.key.data.TicketId; + +public interface TicketRepository extends MongoRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java new file mode 100644 index 000000000000..d4bb1ef40cb8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java @@ -0,0 +1,49 @@ +package com.baeldung.boot.composite.key.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 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/composite/key/data/Sale.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java new file mode 100644 index 000000000000..a81c91674c6d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java @@ -0,0 +1,38 @@ +package com.baeldung.boot.composite.key.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 = "sale_idx", def = "{ 'ticketId': 1 }", unique = true) +public class Sale { + @Id + private String id; + + private TicketId ticketId; + private Double value; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + public TicketId getTicketId() { + return ticketId; + } + + public void setTicketId(TicketId ticketId) { + this.ticketId = ticketId; + } + + 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/composite/key/data/Ticket.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java new file mode 100644 index 000000000000..7a8ebe1ab36f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java @@ -0,0 +1,31 @@ +package com.baeldung.boot.composite.key.data; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Ticket { + @Id + private TicketId id; + + private String event; + + public Ticket() { + } + + public TicketId getId() { + return id; + } + + public void setId(TicketId id) { + this.id = id; + } + + public String getEvent() { + return event; + } + + public void setEvent(String event) { + this.event = event; + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/TicketId.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/TicketId.java new file mode 100644 index 000000000000..76fbf813915c --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/TicketId.java @@ -0,0 +1,56 @@ +package com.baeldung.boot.composite.key.data; + +public class TicketId { + private String venue; + private String date; + + public TicketId() { + } + + public String getVenue() { + return venue; + } + + public void setVenue(String venue) { + this.venue = venue; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((date == null) ? 0 : date.hashCode()); + result = prime * result + ((venue == null) ? 0 : venue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TicketId other = (TicketId) obj; + if (date == null) { + if (other.date != null) + return false; + } else if (!date.equals(other.date)) + return false; + if (venue == null) { + if (other.venue != null) + return false; + } else if (!venue.equals(other.venue)) + return false; + return true; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java new file mode 100644 index 000000000000..476209bce9d3 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java @@ -0,0 +1,66 @@ +package com.baeldung.boot.composite.key.service; + +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.boot.composite.key.dao.CustomerRepository; +import com.baeldung.boot.composite.key.dao.SaleRepository; +import com.baeldung.boot.composite.key.dao.TicketRepository; +import com.baeldung.boot.composite.key.data.Customer; +import com.baeldung.boot.composite.key.data.Sale; +import com.baeldung.boot.composite.key.data.Ticket; +import com.baeldung.boot.composite.key.data.TicketId; + +@Service +public class CustomerService { + @Autowired + private CustomerRepository customerRepository; + + @Autowired + private TicketRepository ticketRepository; + + @Autowired + private SaleRepository saleRepository; + + public Optional find(TicketId id) { + return ticketRepository.findById(id); + } + + public Ticket insert(Ticket ticket) { + return ticketRepository.insert(ticket); + } + + public Ticket save(Ticket ticket) { + return ticketRepository.save(ticket); + } + + public Optional findCustomerById(String id) { + return customerRepository.findById(id); + } + + public Optional findCustomerByIndex(Long storeId, Long number) { + return customerRepository.findByStoreIdAndNumber(storeId, number); + } + + public Customer insert(Customer customer) { + return customerRepository.insert(customer); + } + + public Customer save(Customer customer) { + return customerRepository.save(customer); + } + + public Sale insert(Sale sale) { + return saleRepository.insert(sale); + } + + public Optional findSaleByTicketId(TicketId ticketId) { + return saleRepository.findByTicketId(ticketId); + } + + public Optional findSaleById(String id) { + return saleRepository.findById(id); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java new file mode 100644 index 000000000000..83afe0ae42e0 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java @@ -0,0 +1,88 @@ +package com.baeldung.boot.composite.key.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.composite.key.data.Customer; +import com.baeldung.boot.composite.key.data.Sale; +import com.baeldung.boot.composite.key.data.Ticket; +import com.baeldung.boot.composite.key.data.TicketId; +import com.baeldung.boot.composite.key.service.CustomerService; + +@RestController +@RequestMapping("/customer") +public class CustomerController { + @Autowired + private CustomerService customerService; + + // @Autowired + // private TicketRepository ticketRepository; + // + // @GetMapping("/ticket") + // public Optional getTicket(TicketId id) { + // return ticketRepository.findById(id); + // } + // + // @PostMapping("/ticket") + // public Ticket postTicket(@RequestBody Ticket ticket) { + // return ticketRepository.insert(ticket); + // } + + @GetMapping("/ticket") + public Optional getTicket(TicketId id) { + return customerService.find(id); + } + + @PostMapping("/ticket") + public Ticket postTicket(@RequestBody Ticket ticket) { + return customerService.insert(ticket); + } + + @PutMapping("/ticket") + public Ticket putTicket(@RequestBody Ticket ticket) { + return customerService.save(ticket); + } + + @GetMapping("/{id}") + public Optional getCustomer(@PathVariable String id) { + return customerService.findCustomerById(id); + } + + @GetMapping("/{storeId}/{number}") + public Optional getCustomerByIndex(@PathVariable Long storeId, @PathVariable Long number) { + return customerService.findCustomerByIndex(storeId, number); + } + + @PostMapping + public Customer postCustomer(@RequestBody Customer customer) { + return customerService.insert(customer); + } + + @PutMapping + public Customer putCustomer(@RequestBody Customer customer) { + return customerService.save(customer); + } + + @PostMapping("/sale") + public Sale postSale(@RequestBody Sale sale) { + return customerService.insert(sale); + } + + @GetMapping("/sale/{id}") + public Optional getSale(@PathVariable String id) { + return customerService.findSaleById(id); + } + + @GetMapping("/sale") + public Optional getSale(TicketId ticketId) { + return customerService.findSaleByTicketId(ticketId); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties new file mode 100644 index 000000000000..a73a94d850b4 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/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/composite/key/CustomerServiceIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java new file mode 100644 index 000000000000..4f779ebf0201 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java @@ -0,0 +1,140 @@ +package com.baeldung.boot.composite.key; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.util.Optional; + +import org.junit.BeforeClass; +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.composite.key.data.Customer; +import com.baeldung.boot.composite.key.data.Ticket; +import com.baeldung.boot.composite.key.data.TicketId; +import com.baeldung.boot.composite.key.service.CustomerService; + +@SpringBootTest +@DirtiesContext +@RunWith(SpringRunner.class) +public class CustomerServiceIntegrationTest { + @Autowired + private CustomerService service; + + private static Ticket ticket; + private static TicketId ticketId; + + @BeforeClass + public static void setup() { + ticket = new Ticket(); + ticket.setEvent("Event A"); + + ticketId = new TicketId(); + ticketId.setDate("2020-01-01"); + ticketId.setVenue("Venue A"); + ticket.setId(ticketId); + } + + @Test + public void givenCompositeId_whenObjectSaved_thenIdMatches() { + Ticket savedTicket = service.insert(ticket); + assertEquals(savedTicket.getId(), ticket.getId()); + } + + @Test + public void givenCompositeId_whenSearchingByIdObject_thenFound() { + Optional optionalTicket = service.find(ticketId); + + assertThat(optionalTicket.isPresent()); + Ticket savedTicket = optionalTicket.get(); + + assertEquals(savedTicket.getId(), ticketId); + } + + @Test + public void givenCompoundUniqueIndex_whenSearchingByGeneratedId_thenFound() { + Customer customer = new Customer(); + customer.setName("Name"); + customer.setNumber(0l); + customer.setStoreId(0l); + + Customer savedCustomer = service.insert(customer); + + Optional optional = service.findCustomerById(savedCustomer.getId()); + + assertThat(optional.isPresent()); + } + + @Test + public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() { + Ticket ticket = new Ticket(); + ticket.setEvent("C"); + + TicketId ticketId = new TicketId(); + ticketId.setDate("2020-01-01"); + ticketId.setVenue("V"); + ticket.setId(ticketId); + + assertThrows(DuplicateKeyException.class, () -> { + service.insert(ticket); + service.insert(ticket); + }); + } + + @Test + public void givenCompositeId_whenDupeSave_thenObjectUpdated() { + TicketId ticketId = new TicketId(); + ticketId.setDate("2020-01-01"); + ticketId.setVenue("Venue"); + + Ticket ticketA = new Ticket(); + ticketA.setEvent("A"); + ticketA.setId(ticketId); + + service.save(ticketA); + + Ticket ticketB = new Ticket(); + ticketB.setEvent("B"); + ticketB.setId(ticketId); + + Ticket savedTicket = service.save(ticketB); + assertEquals(savedTicket.getEvent(), ticketB.getEvent()); + } + + @Test + public void givenCompoundUniqueIndex_whenDupeInsert_thenExceptionIsThrown() { + Customer customer = new Customer(); + customer.setName("Name"); + customer.setNumber(1l); + customer.setStoreId(2l); + + assertThrows(DuplicateKeyException.class, () -> { + service.insert(customer); + service.insert(customer); + }); + } + + @Test + public void givenCompoundUniqueIndex_whenDupeSave_thenExceptionIsThrown() { + Customer customerA = new Customer(); + customerA.setName("Name A"); + customerA.setNumber(1l); + customerA.setStoreId(2l); + + Customer customerB = new Customer(); + customerB.setName("Name B"); + customerB.setNumber(1l); + customerB.setStoreId(2l); + + assertThrows(DuplicateKeyException.class, () -> { + service.save(customerA); + service.save(customerB); + }); + } +} From fcee00f63d12d320188cd4d880b76f721fef377f Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Fri, 27 May 2022 23:57:12 -0300 Subject: [PATCH 2/7] removing comments --- .../boot/composite/key/web/CustomerController.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java index 83afe0ae42e0..9e41d13e1494 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java @@ -23,19 +23,6 @@ public class CustomerController { @Autowired private CustomerService customerService; - // @Autowired - // private TicketRepository ticketRepository; - // - // @GetMapping("/ticket") - // public Optional getTicket(TicketId id) { - // return ticketRepository.findById(id); - // } - // - // @PostMapping("/ticket") - // public Ticket postTicket(@RequestBody Ticket ticket) { - // return ticketRepository.insert(ticket); - // } - @GetMapping("/ticket") public Optional getTicket(TicketId id) { return customerService.find(id); From aed776f40631eecc4b7356ff2ab337a7bf20097d Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Fri, 3 Jun 2022 10:06:51 -0300 Subject: [PATCH 3/7] BAEL-5370 Test could fail if ran in a different order: givenCompositeId_whenSearchingByIdObject_thenFound --- .../boot/composite/key/data/Ticket.java | 6 +++ .../key/CustomerServiceIntegrationTest.java | 42 +++++++------------ 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java index 7a8ebe1ab36f..d77b54c51359 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Ticket.java @@ -13,6 +13,12 @@ public class Ticket { public Ticket() { } + public Ticket(TicketId id, String event) { + super(); + this.id = id; + this.event = event; + } + public TicketId getId() { return id; } diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java index 4f779ebf0201..658be343f1b1 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java @@ -6,7 +6,6 @@ import java.util.Optional; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -27,28 +26,26 @@ public class CustomerServiceIntegrationTest { @Autowired private CustomerService service; - private static Ticket ticket; - private static TicketId ticketId; - - @BeforeClass - public static void setup() { - ticket = new Ticket(); - ticket.setEvent("Event A"); - - ticketId = new TicketId(); + @Test + public void givenCompositeId_whenObjectSaved_thenIdMatches() { + TicketId ticketId = new TicketId(); ticketId.setDate("2020-01-01"); ticketId.setVenue("Venue A"); - ticket.setId(ticketId); - } - @Test - public void givenCompositeId_whenObjectSaved_thenIdMatches() { + Ticket ticket = new Ticket(ticketId, "Event A"); Ticket savedTicket = service.insert(ticket); + assertEquals(savedTicket.getId(), ticket.getId()); } @Test public void givenCompositeId_whenSearchingByIdObject_thenFound() { + TicketId ticketId = new TicketId(); + ticketId.setDate("2020-01-01"); + ticketId.setVenue("Venue B"); + + service.insert(new Ticket(ticketId, "Event B")); + Optional optionalTicket = service.find(ticketId); assertThat(optionalTicket.isPresent()); @@ -73,13 +70,11 @@ public void givenCompoundUniqueIndex_whenSearchingByGeneratedId_thenFound() { @Test public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() { - Ticket ticket = new Ticket(); - ticket.setEvent("C"); - TicketId ticketId = new TicketId(); ticketId.setDate("2020-01-01"); ticketId.setVenue("V"); - ticket.setId(ticketId); + + Ticket ticket = new Ticket(ticketId, "Event C"); assertThrows(DuplicateKeyException.class, () -> { service.insert(ticket); @@ -93,17 +88,12 @@ public void givenCompositeId_whenDupeSave_thenObjectUpdated() { ticketId.setDate("2020-01-01"); ticketId.setVenue("Venue"); - Ticket ticketA = new Ticket(); - ticketA.setEvent("A"); - ticketA.setId(ticketId); - + Ticket ticketA = new Ticket(ticketId, "A"); service.save(ticketA); - Ticket ticketB = new Ticket(); - ticketB.setEvent("B"); - ticketB.setId(ticketId); - + Ticket ticketB = new Ticket(ticketId, "B"); Ticket savedTicket = service.save(ticketB); + assertEquals(savedTicket.getEvent(), ticketB.getEvent()); } From 0e4ff37f9878e63366bf5d37f2ce0308ed339a29 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Mon, 13 Jun 2022 23:37:28 -0300 Subject: [PATCH 4/7] BAEL-5370 removing compound index related stuff --- .../SpringBootCompositeKeyApplication.java | 2 - .../composite/key/dao/CustomerRepository.java | 12 ----- .../composite/key/dao/SaleRepository.java | 12 ----- .../boot/composite/key/data/Customer.java | 49 ------------------- .../boot/composite/key/data/Sale.java | 38 -------------- .../key/service/CustomerService.java | 38 -------------- .../composite/key/web/CustomerController.java | 38 -------------- .../boot.composite.key/app.properties | 1 - .../key/CustomerServiceIntegrationTest.java | 46 ----------------- 9 files changed, 236 deletions(-) delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java index e9f8eab1dd50..1322adbf77d5 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/SpringBootCompositeKeyApplication.java @@ -2,11 +2,9 @@ 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.composite.key/app.properties") @EnableMongoRepositories(basePackages = { "com.baeldung.boot.composite.key" }) public class SpringBootCompositeKeyApplication { public static void main(String... args) { diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java deleted file mode 100644 index 6953a21ddd5e..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/CustomerRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.boot.composite.key.dao; - -import java.util.Optional; - -import org.springframework.data.mongodb.repository.MongoRepository; - -import com.baeldung.boot.composite.key.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/composite/key/dao/SaleRepository.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java deleted file mode 100644 index 3caa33d4658e..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/dao/SaleRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.boot.composite.key.dao; - -import java.util.Optional; - -import org.springframework.data.mongodb.repository.MongoRepository; - -import com.baeldung.boot.composite.key.data.Sale; -import com.baeldung.boot.composite.key.data.TicketId; - -public interface SaleRepository extends MongoRepository { - Optional findByTicketId(TicketId ticketId); -} diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java deleted file mode 100644 index d4bb1ef40cb8..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Customer.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.boot.composite.key.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 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/composite/key/data/Sale.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java deleted file mode 100644 index a81c91674c6d..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/data/Sale.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.boot.composite.key.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 = "sale_idx", def = "{ 'ticketId': 1 }", unique = true) -public class Sale { - @Id - private String id; - - private TicketId ticketId; - private Double value; - - public String getId() { - return id; - } - public void setId(String id) { - this.id = id; - } - - public TicketId getTicketId() { - return ticketId; - } - - public void setTicketId(TicketId ticketId) { - this.ticketId = ticketId; - } - - 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/composite/key/service/CustomerService.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java index 476209bce9d3..90ca1b758d77 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/service/CustomerService.java @@ -5,25 +5,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.baeldung.boot.composite.key.dao.CustomerRepository; -import com.baeldung.boot.composite.key.dao.SaleRepository; import com.baeldung.boot.composite.key.dao.TicketRepository; -import com.baeldung.boot.composite.key.data.Customer; -import com.baeldung.boot.composite.key.data.Sale; import com.baeldung.boot.composite.key.data.Ticket; import com.baeldung.boot.composite.key.data.TicketId; @Service public class CustomerService { - @Autowired - private CustomerRepository customerRepository; - @Autowired private TicketRepository ticketRepository; - @Autowired - private SaleRepository saleRepository; - public Optional find(TicketId id) { return ticketRepository.findById(id); } @@ -35,32 +25,4 @@ public Ticket insert(Ticket ticket) { public Ticket save(Ticket ticket) { return ticketRepository.save(ticket); } - - public Optional findCustomerById(String id) { - return customerRepository.findById(id); - } - - public Optional findCustomerByIndex(Long storeId, Long number) { - return customerRepository.findByStoreIdAndNumber(storeId, number); - } - - public Customer insert(Customer customer) { - return customerRepository.insert(customer); - } - - public Customer save(Customer customer) { - return customerRepository.save(customer); - } - - public Sale insert(Sale sale) { - return saleRepository.insert(sale); - } - - public Optional findSaleByTicketId(TicketId ticketId) { - return saleRepository.findByTicketId(ticketId); - } - - public Optional findSaleById(String id) { - return saleRepository.findById(id); - } } diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java index 9e41d13e1494..4379a46d0534 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/composite/key/web/CustomerController.java @@ -4,15 +4,12 @@ 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.composite.key.data.Customer; -import com.baeldung.boot.composite.key.data.Sale; import com.baeldung.boot.composite.key.data.Ticket; import com.baeldung.boot.composite.key.data.TicketId; import com.baeldung.boot.composite.key.service.CustomerService; @@ -37,39 +34,4 @@ public Ticket postTicket(@RequestBody Ticket ticket) { public Ticket putTicket(@RequestBody Ticket ticket) { return customerService.save(ticket); } - - @GetMapping("/{id}") - public Optional getCustomer(@PathVariable String id) { - return customerService.findCustomerById(id); - } - - @GetMapping("/{storeId}/{number}") - public Optional getCustomerByIndex(@PathVariable Long storeId, @PathVariable Long number) { - return customerService.findCustomerByIndex(storeId, number); - } - - @PostMapping - public Customer postCustomer(@RequestBody Customer customer) { - return customerService.insert(customer); - } - - @PutMapping - public Customer putCustomer(@RequestBody Customer customer) { - return customerService.save(customer); - } - - @PostMapping("/sale") - public Sale postSale(@RequestBody Sale sale) { - return customerService.insert(sale); - } - - @GetMapping("/sale/{id}") - public Optional getSale(@PathVariable String id) { - return customerService.findSaleById(id); - } - - @GetMapping("/sale") - public Optional getSale(TicketId ticketId) { - return customerService.findSaleByTicketId(ticketId); - } } diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties deleted file mode 100644 index a73a94d850b4..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/resources/boot.composite.key/app.properties +++ /dev/null @@ -1 +0,0 @@ -spring.data.mongodb.auto-index-creation=true diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java index 658be343f1b1..1aee478ad0c9 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java @@ -14,7 +14,6 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.boot.composite.key.data.Customer; import com.baeldung.boot.composite.key.data.Ticket; import com.baeldung.boot.composite.key.data.TicketId; import com.baeldung.boot.composite.key.service.CustomerService; @@ -54,20 +53,6 @@ public void givenCompositeId_whenSearchingByIdObject_thenFound() { assertEquals(savedTicket.getId(), ticketId); } - @Test - public void givenCompoundUniqueIndex_whenSearchingByGeneratedId_thenFound() { - Customer customer = new Customer(); - customer.setName("Name"); - customer.setNumber(0l); - customer.setStoreId(0l); - - Customer savedCustomer = service.insert(customer); - - Optional optional = service.findCustomerById(savedCustomer.getId()); - - assertThat(optional.isPresent()); - } - @Test public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() { TicketId ticketId = new TicketId(); @@ -96,35 +81,4 @@ public void givenCompositeId_whenDupeSave_thenObjectUpdated() { assertEquals(savedTicket.getEvent(), ticketB.getEvent()); } - - @Test - public void givenCompoundUniqueIndex_whenDupeInsert_thenExceptionIsThrown() { - Customer customer = new Customer(); - customer.setName("Name"); - customer.setNumber(1l); - customer.setStoreId(2l); - - assertThrows(DuplicateKeyException.class, () -> { - service.insert(customer); - service.insert(customer); - }); - } - - @Test - public void givenCompoundUniqueIndex_whenDupeSave_thenExceptionIsThrown() { - Customer customerA = new Customer(); - customerA.setName("Name A"); - customerA.setNumber(1l); - customerA.setStoreId(2l); - - Customer customerB = new Customer(); - customerB.setName("Name B"); - customerB.setNumber(1l); - customerB.setStoreId(2l); - - assertThrows(DuplicateKeyException.class, () -> { - service.save(customerA); - service.save(customerB); - }); - } } From fc38f6600625db9e07e9d2fc4e7f3a2d90cd4047 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Fri, 17 Jun 2022 12:01:44 -0300 Subject: [PATCH 5/7] removing first insert from assertThrows --- .../boot/composite/key/CustomerServiceIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java index 1aee478ad0c9..af310ab29ebb 100644 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb-2/src/test/java/com/baeldung/boot/composite/key/CustomerServiceIntegrationTest.java @@ -60,10 +60,10 @@ public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() { ticketId.setVenue("V"); Ticket ticket = new Ticket(ticketId, "Event C"); + service.insert(ticket); assertThrows(DuplicateKeyException.class, () -> { service.insert(ticket); - service.insert(ticket); }); } From 7cad99928721c39702c2a769968a8f8d3f4b7372 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Sun, 19 Jun 2022 16:32:10 -0300 Subject: [PATCH 6/7] 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 000000000000..648ecd4dfb1f --- /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 000000000000..9adca8b4bd7e --- /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 000000000000..718e284efe60 --- /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 000000000000..6afe0046095d --- /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 000000000000..f6e5b54470ed --- /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 000000000000..8547a5ab7682 --- /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 000000000000..9652691a8bf8 --- /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 000000000000..31b4cf0588ba --- /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 000000000000..d1459dc663c7 --- /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 000000000000..523a0a98413a --- /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 000000000000..3d0a54957572 --- /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 000000000000..69a5c5a561c2 --- /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 000000000000..8ac00c497f0b --- /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 000000000000..a73a94d850b4 --- /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 000000000000..c18a877b797a --- /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); + }); + } +} From 1cbffa7446337b718aaa18dcac8b8fed12f42ea2 Mon Sep 17 00:00:00 2001 From: Ulisses Lima Date: Sun, 19 Jun 2022 16:35:36 -0300 Subject: [PATCH 7/7] removing Customer2 --- .../unique/field/dao/Customer2Repository.java | 8 ---- .../boot/unique/field/data/Customer2.java | 47 ------------------- .../field/web/UniqueFieldController.java | 10 ---- 3 files changed, 65 deletions(-) delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java delete mode 100644 persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java 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 deleted file mode 100644 index 6afe0046095d..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/dao/Customer2Repository.java +++ /dev/null @@ -1,8 +0,0 @@ -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/data/Customer2.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java deleted file mode 100644 index 523a0a98413a..000000000000 --- a/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/data/Customer2.java +++ /dev/null @@ -1,47 +0,0 @@ -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/web/UniqueFieldController.java b/persistence-modules/spring-boot-persistence-mongodb-2/src/main/java/com/baeldung/boot/unique/field/web/UniqueFieldController.java index 8ac00c497f0b..716977edd465 100644 --- 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 @@ -13,13 +13,11 @@ 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; @@ -35,9 +33,6 @@ public class UniqueFieldController { @Autowired private CustomerRepository customerRepo; - @Autowired - private Customer2Repository customer2Repo; - @Autowired private AssetRepository assetRepo; @@ -71,11 +66,6 @@ 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);