Merge branch 'eugenp:master' into master

This commit is contained in:
sebx59
2022-06-27 15:09:27 +02:00
committed by GitHub
2868 changed files with 6351 additions and 4052 deletions
@@ -0,0 +1,46 @@
package com.baeldung.hibernate.exception.detachedentity;
import java.util.Properties;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
import com.baeldung.hibernate.exception.detachedentity.entity.Comment;
import com.baeldung.hibernate.exception.detachedentity.entity.Post;
public class HibernateUtil {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
Configuration configuration = new Configuration();
Properties settings = new Properties();
settings.put(Environment.DRIVER, "org.hsqldb.jdbcDriver");
settings.put(Environment.URL, "jdbc:hsqldb:mem:transient");
settings.put(Environment.USER, "sa");
settings.put(Environment.PASS, "");
settings.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect");
settings.put(Environment.SHOW_SQL, "true");
settings.put(Environment.FORMAT_SQL, "true");
settings.put(Environment.USE_SQL_COMMENTS, "true");
settings.put(Environment.HBM2DDL_AUTO, "update");
configuration.setProperties(settings);
configuration.addAnnotatedClass(Comment.class);
configuration.addAnnotatedClass(Post.class);
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties())
.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}
}
@@ -0,0 +1,56 @@
package com.baeldung.hibernate.exception.detachedentity.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String text;
public Comment(String text) {
this.text = text;
}
public Comment() {
}
@ManyToOne
private Post post;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
@Override
public String toString() {
return "Comment{" + "id=" + id + ", name='" + text + '\'' + ", post=" + post + '}';
}
}
@@ -0,0 +1,44 @@
package com.baeldung.hibernate.exception.detachedentity.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
public Post() {
}
public Post(String title) {
this.title = title;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Post{" + "id=" + id + ", text='" + title + '\'' + '}';
}
}
@@ -0,0 +1,106 @@
package com.baeldung.hibernate.exception.detachedentity;
import com.baeldung.hibernate.exception.detachedentity.entity.Comment;
import com.baeldung.hibernate.exception.detachedentity.entity.Post;
import org.assertj.core.api.Assertions;
import org.hibernate.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.PersistenceException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class DetachedEntityUnitTest {
private static Session session;
private Post detachedPost;
@Before
public void beforeEach() {
session = HibernateUtil.getSessionFactory()
.openSession();
session.beginTransaction();
this.detachedPost = new Post("Hibernate Tutorial");
session.persist(detachedPost);
session.evict(detachedPost);
}
@After
public void afterEach() {
clearDatabase();
session.close();
}
@Test
public void givenDetachedPost_whenTryingToPersist_thenThrowException() {
detachedPost.setTitle("Hibernate Tutorial for Absolute Beginners");
assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class)
.hasMessageContaining("org.hibernate.PersistentObjectException: detached entity passed to persist");
}
@Test
public void givenDetachedPost_whenTryingToMerge_thenNoExceptionIsThrown() {
detachedPost.setTitle("Hibernate Tutorial for Beginners");
session.merge(detachedPost);
session.getTransaction()
.commit();
List<Post> posts = session.createQuery("Select p from Post p", Post.class)
.list();
assertThat(posts).hasSize(1);
assertThat(posts.get(0)
.getTitle()).isEqualTo("Hibernate Tutorial for Beginners");
}
@Test
public void givenDetachedPost_whenPersistingNewCommentWithIt_thenThrowException() {
Comment comment = new Comment("nice article!");
comment.setPost(detachedPost);
session.persist(comment);
session.getTransaction()
.commit();
assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class)
.hasMessageContaining("org.hibernate.PersistentObjectException: detached entity passed to persist");
}
@Test
public void givenDetachedPost_whenMergeAndPersistComment_thenNoExceptionIsThrown() {
Comment comment = new Comment("nice article!");
Post mergedPost = (Post) session.merge(detachedPost);
comment.setPost(mergedPost);
session.persist(comment);
session.getTransaction()
.commit();
List<Comment> comments = session.createQuery("Select c from Comment c", Comment.class)
.list();
Comment savedComment = comments.get(0);
assertThat(savedComment.getText()).isEqualTo("nice article!");
assertThat(savedComment.getPost()
.getTitle()).isEqualTo("Hibernate Tutorial");
}
private void clearDatabase() {
if (!session.getTransaction()
.isActive()) {
session.beginTransaction();
}
session.createQuery("DELETE FROM Comment")
.executeUpdate();
session.createQuery("DELETE FROM Post")
.executeUpdate();
}
}
@@ -0,0 +1,5 @@
.classpath
.project
.settings
target
build
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>java-mongodb-3</artifactId>
<version>1.0-SNAPSHOT</version>
<name>java-mongodb-3</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>persistence-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
</dependencies>
<properties>
<mongo.version>3.12.1</mongo.version>
</properties>
</project>
@@ -0,0 +1,86 @@
package com.baeldung.mongo.find;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.conversions.Bson;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;
public class FindOperation {
private static MongoClient mongoClient;
private static MongoDatabase database;
private static MongoCollection<Document> collection;
private static String collectionName;
private static String databaseName;
public static void setUp() {
if (mongoClient == null) {
mongoClient = new MongoClient("localhost", 27017);
databaseName = "baeldung";
collectionName = "employee";
database = mongoClient.getDatabase(databaseName);
collection = database.getCollection(collectionName);
}
}
public static void retrieveAllDocumentsUsingFind() {
FindIterable<Document> documents = collection.find();
MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
public static void retrieveAllDocumentsUsingFindWithQueryFilter() {
Bson filter = eq("department", "Engineering");
FindIterable<Document> documents = collection.find(filter);
MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
public static void retrieveAllDocumentsUsingFindWithQueryFilterAndProjection() {
Bson filter = eq("department", "Engineering");
Bson projection = fields(include("name", "age"));
FindIterable<Document> documents = collection.find(filter)
.projection(projection);
MongoCursor<Document> cursor = documents.iterator();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
}
public static void retrieveFirstDocument() {
FindIterable<Document> documents = collection.find();
Document document = documents.first();
System.out.println(document);
}
public static void main(String args[]) {
setUp();
retrieveAllDocumentsUsingFind();
retrieveAllDocumentsUsingFindWithQueryFilter();
retrieveAllDocumentsUsingFindWithQueryFilterAndProjection();
retrieveFirstDocument();
}
}
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,94 @@
package com.baeldung.mongo.find;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Projections.fields;
import static com.mongodb.client.model.Projections.include;
import static org.junit.Assert.*;
public class FindOperationLiveTest {
private static MongoClient mongoClient;
private static MongoDatabase database;
private static MongoCollection<Document> collection;
private static final String DATASET_JSON = "/employee.json";
@BeforeClass
public static void setUp() throws IOException {
if (mongoClient == null) {
mongoClient = new MongoClient("localhost", 27017);
database = mongoClient.getDatabase("baeldung");
collection = database.getCollection("employee");
collection.drop();
InputStream is = FindOperationLiveTest.class.getResourceAsStream(DATASET_JSON);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
reader.lines()
.forEach(line -> collection.insertOne(Document.parse(line)));
reader.close();
}
}
@Test
public void givenEmployeeCollection_whenFetchingUsingFindOperations_thenCheckingForDocuments() {
FindIterable<Document> documents = collection.find();
MongoCursor<Document> cursor = documents.iterator();
assertNotNull(cursor);
assertTrue(cursor.hasNext());
}
@Test
public void givenEmployeeCollection_whenFetchingUsingFindOperationsWithFilters_thenCheckingForDocuments() {
Bson filter = eq("department", "Engineering");
FindIterable<Document> documents = collection.find(filter);
MongoCursor<Document> cursor = documents.iterator();
assertNotNull(cursor);
assertTrue(cursor.hasNext());
}
@Test
public void givenEmployeeCollection_whenFetchingUsingFindOperationsWithFiltersAndProjection_thenCheckingForDocuments() {
Bson filter = eq("department", "Engineering");
Bson projection = fields(include("name", "age"));
FindIterable<Document> documents = collection.find(filter)
.projection(projection);
MongoCursor<Document> cursor = documents.iterator();
assertNotNull(cursor);
assertTrue(cursor.hasNext());
}
@Test
public void givenEmployeeCollection_whenFetchingFirstDocumentUsingFindOperations_thenCheckingForDocument() {
Document employee = collection.find()
.first();
assertNotNull(employee);
assertFalse(employee.isEmpty());
}
@AfterClass
public static void cleanUp() {
mongoClient.close();
}
}
@@ -0,0 +1,3 @@
{"employeeId":"EMP1","name":"Sam","age":23,"type":"Full Time","department":"Engineering"}
{"employeeId":"EMP2","name":"Tony","age":31,"type":"Full Time","department":"Admin"}
{"employeeId":"EMP3","name":"Lisa","age":42,"type":"Part Time","department":"Engineering"}
+2
View File
@@ -44,6 +44,7 @@
<module>java-jpa-3</module>
<module>java-mongodb</module> <!-- long running -->
<module>java-mongodb-2</module> <!-- long running -->
<module>java-mongodb-3</module> <!-- long running -->
<module>jnosql</module> <!-- long running -->
<module>jooq</module>
<module>jpa-hibernate-cascade-type</module>
@@ -87,6 +88,7 @@
<module>spring-data-jdbc</module>
<module>spring-data-keyvalue</module>
<module>spring-data-mongodb</module>
<module>spring-data-mongodb-2</module>
<module>spring-data-mongodb-reactive</module>
<module>spring-data-neo4j</module>
<module>spring-data-redis</module>
@@ -2,4 +2,5 @@
- [Logging MongoDB Queries with Spring Boot](https://www.baeldung.com/spring-boot-mongodb-logging)
- [Configure MongoDB Collection Name for a Class in Spring Data](https://www.baeldung.com/spring-data-mongodb-collection-name)
- [MongoDB Composite Key With Spring Data](https://www.baeldung.com/spring-data-mongodb-composite-key)
- More articles: [[<--prev]](../spring-boot-persistence-mongodb)
@@ -0,0 +1,13 @@
package com.baeldung.boot.composite.key;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
@SpringBootApplication
@EnableMongoRepositories(basePackages = { "com.baeldung.boot.composite.key" })
public class SpringBootCompositeKeyApplication {
public static void main(String... args) {
SpringApplication.run(SpringBootCompositeKeyApplication.class, args);
}
}
@@ -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<Ticket, TicketId> {
}
@@ -0,0 +1,37 @@
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 Ticket(TicketId id, String event) {
super();
this.id = id;
this.event = event;
}
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;
}
}
@@ -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;
}
}
@@ -0,0 +1,28 @@
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.TicketRepository;
import com.baeldung.boot.composite.key.data.Ticket;
import com.baeldung.boot.composite.key.data.TicketId;
@Service
public class CustomerService {
@Autowired
private TicketRepository ticketRepository;
public Optional<Ticket> 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);
}
}
@@ -0,0 +1,37 @@
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.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.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;
@GetMapping("/ticket")
public Optional<Ticket> 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);
}
}
@@ -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);
}
}
@@ -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<Asset, String> {
}
@@ -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<Company, String> {
Optional<Company> findByEmail(String email);
}
@@ -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<Customer, String> {
Optional<Customer> findByStoreIdAndNumber(Long storeId, Long number);
}
@@ -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<Sale, String> {
Optional<Sale> findBySaleId(SaleId id);
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -0,0 +1,83 @@
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.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;
@RestController
@RequestMapping("/unique-field")
public class UniqueFieldController {
@Autowired
private SaleRepository saleRepo;
@Autowired
private CompanyRepository companyRepo;
@Autowired
private CustomerRepository customerRepo;
@Autowired
private AssetRepository assetRepo;
@PostMapping("/sale")
public Sale post(@RequestBody Sale sale) {
return saleRepo.insert(sale);
}
@GetMapping("/sale")
public Optional<Sale> 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<Company> getCompany(@PathVariable String id) {
return companyRepo.findById(id);
}
@PostMapping("/customer")
public Customer post(@RequestBody Customer customer) {
return customerRepo.insert(customer);
}
@GetMapping("/customer/{id}")
public Optional<Customer> 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<Asset> getAsset(@PathVariable String id) {
return assetRepo.findById(id);
}
}
@@ -0,0 +1 @@
spring.data.mongodb.auto-index-creation=true
@@ -0,0 +1,84 @@
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.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.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;
@Test
public void givenCompositeId_whenObjectSaved_thenIdMatches() {
TicketId ticketId = new TicketId();
ticketId.setDate("2020-01-01");
ticketId.setVenue("Venue A");
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<Ticket> optionalTicket = service.find(ticketId);
assertThat(optionalTicket.isPresent());
Ticket savedTicket = optionalTicket.get();
assertEquals(savedTicket.getId(), ticketId);
}
@Test
public void givenCompositeId_whenDupeInsert_thenExceptionIsThrown() {
TicketId ticketId = new TicketId();
ticketId.setDate("2020-01-01");
ticketId.setVenue("V");
Ticket ticket = new Ticket(ticketId, "Event C");
service.insert(ticket);
assertThrows(DuplicateKeyException.class, () -> {
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(ticketId, "A");
service.save(ticketA);
Ticket ticketB = new Ticket(ticketId, "B");
Ticket savedTicket = service.save(ticketB);
assertEquals(savedTicket.getEvent(), ticketB.getEvent());
}
}
@@ -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);
});
}
}
@@ -0,0 +1,7 @@
=========
## Spring Data MongoDB 2
### Relevant Articles:
- [Return Only Specific Fields for a Query in Spring Data MongoDB](https://www.baeldung.com/mongodb-return-specific-fields)
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-mongodb-2</artifactId>
<name>spring-data-mongodb-2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-spring-5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-spring-5</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${org.springframework.data.version}</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>${mongodb-driver.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>${embed.mongo.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<org.springframework.data.version>3.0.3.RELEASE</org.springframework.data.version>
<mongodb-driver.version>4.0.5</mongodb-driver.version>
<embed.mongo.version>3.2.6</embed.mongo.version>
</properties>
</project>
@@ -11,7 +11,6 @@
- [Spring Data MongoDB: Projections and Aggregations](http://www.baeldung.com/spring-data-mongodb-projections-aggregations)
- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations)
- [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions)
- [Return Only Specific Fields for a Query in Spring Data MongoDB](https://www.baeldung.com/mongodb-return-specific-fields)
## Spring Data MongoDB Live Testing