Merge branch 'eugenp:master' into master
This commit is contained in:
+46
@@ -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;
|
||||
}
|
||||
}
|
||||
+56
@@ -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 + '}';
|
||||
}
|
||||
}
|
||||
+44
@@ -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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
+106
@@ -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>
|
||||
+86
@@ -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>
|
||||
+94
@@ -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"}
|
||||
@@ -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)
|
||||
|
||||
+13
@@ -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);
|
||||
}
|
||||
}
|
||||
+10
@@ -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> {
|
||||
|
||||
}
|
||||
+37
@@ -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;
|
||||
}
|
||||
}
|
||||
+56
@@ -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;
|
||||
}
|
||||
}
|
||||
+28
@@ -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);
|
||||
}
|
||||
}
|
||||
+37
@@ -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);
|
||||
}
|
||||
}
|
||||
+15
@@ -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);
|
||||
}
|
||||
}
|
||||
+8
@@ -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> {
|
||||
}
|
||||
+11
@@ -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);
|
||||
}
|
||||
+11
@@ -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);
|
||||
}
|
||||
+12
@@ -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);
|
||||
}
|
||||
+29
@@ -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;
|
||||
}
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
+57
@@ -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;
|
||||
}
|
||||
}
|
||||
+36
@@ -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;
|
||||
}
|
||||
}
|
||||
+22
@@ -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;
|
||||
}
|
||||
}
|
||||
+83
@@ -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);
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
spring.data.mongodb.auto-index-creation=true
|
||||
+84
@@ -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());
|
||||
}
|
||||
}
|
||||
+112
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user