From af124509c861975a80c83a722fa10c6014e17afc Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 4 Oct 2021 13:45:37 +0200 Subject: [PATCH] Add MongoDB example for linking documents. Closes #631 --- README.md | 1 + mongodb/linking/README.md | 62 ++++++++++++++ mongodb/linking/pom.xml | 15 ++++ .../dbref/ApplicationConfiguration.java | 24 ++++++ .../mongodb/linking/dbref/Employee.java | 64 +++++++++++++++ .../mongodb/linking/dbref/Manager.java | 66 +++++++++++++++ .../jpastyle/ApplicationConfiguration.java | 26 ++++++ .../linking/docref/jpastyle/Employee.java | 65 +++++++++++++++ .../linking/docref/jpastyle/Manager.java | 72 +++++++++++++++++ .../query/ApplicationConfiguration.java | 24 ++++++ .../linking/docref/query/Employee.java | 64 +++++++++++++++ .../mongodb/linking/docref/query/Manager.java | 70 ++++++++++++++++ .../simple/ApplicationConfiguration.java | 24 ++++++ .../linking/docref/simple/Employee.java | 65 +++++++++++++++ .../linking/docref/simple/Manager.java | 70 ++++++++++++++++ .../mongodb/linking/dbref/DBRefTests.java | 81 +++++++++++++++++++ .../docref/jpastyle/JpaStyleDocRefTests.java | 70 ++++++++++++++++ .../docref/query/QueryDocRefTests.java | 81 +++++++++++++++++++ .../docref/simple/SimpleDocRefTests.java | 81 +++++++++++++++++++ .../src/test/resources/application.properties | 3 + mongodb/pom.xml | 1 + 21 files changed, 1029 insertions(+) create mode 100644 mongodb/linking/README.md create mode 100644 mongodb/linking/pom.xml create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/ApplicationConfiguration.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Employee.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Manager.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/ApplicationConfiguration.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Employee.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Manager.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/ApplicationConfiguration.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Employee.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Manager.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/ApplicationConfiguration.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Employee.java create mode 100644 mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Manager.java create mode 100644 mongodb/linking/src/test/java/example/springdata/mongodb/linking/dbref/DBRefTests.java create mode 100644 mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/jpastyle/JpaStyleDocRefTests.java create mode 100644 mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/query/QueryDocRefTests.java create mode 100644 mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/simple/SimpleDocRefTests.java create mode 100644 mongodb/linking/src/test/resources/application.properties diff --git a/README.md b/README.md index b6671009..ed45cee5 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Local Elasticsearch instance must be running to run the tests. * `gridfs` - Example project showing usage of gridFS with MongoDB. * `jmolecules` - Example of Spring Data MongoDB working with a jMolecules based domain model. * `kotlin` - Example for using [Kotlin](https://kotlinlang.org/) with MongoDB. +* `linking` - Example demonstrating possibilities for linking documents. * `query-by-example` - Example project showing usage of Query by Example with MongoDB. * `querydsl` - Example project showing imperative and reactive [Querydsl](https://github.com/querydsl/querydsl) support for MongoDB. * `reactive` - Example project to show reactive template and repository support. diff --git a/mongodb/linking/README.md b/mongodb/linking/README.md new file mode 100644 index 00000000..c550b1ed --- /dev/null +++ b/mongodb/linking/README.md @@ -0,0 +1,62 @@ +# Spring Data MongoDB - Linking Example + +This project contains examples for linking Documents using: + +* `@DBRef` +* `@DocumentReference` + +## DBRef + +Use MongoDB native `dbref` for storing associations. + +```java +class Manager { + + @DBRef + private List employees; + + // ... +} +``` + +## DocumentReference + +Link documents via their id. + +```java +class Manager { + + @DocumentReference + private List employees; + + // ... +} +``` + +Link documents via a (non _id_) property. + +```java +class Manager { + + @DocumentReference(lookup = "{ 'name' : ?#{#target} }") + private List employees; + + // ... +} +``` + +Link documents JPA style. + +```java +class Manager { + + @ReadOnlyProperty + @DocumentReference(lookup="{'managerId':?#{#self._id} }") + private List employees; + + // ... +} +``` +---- + +For more information please refer to the [Reference Documentation](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-usage-references). diff --git a/mongodb/linking/pom.xml b/mongodb/linking/pom.xml new file mode 100644 index 00000000..668bd502 --- /dev/null +++ b/mongodb/linking/pom.xml @@ -0,0 +1,15 @@ + + 4.0.0 + + spring-data-mongodb-linking-example + + Spring Data MongoDB - Linking Example + + + org.springframework.data.examples + spring-data-mongodb-examples + 2.0.0.BUILD-SNAPSHOT + + + diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/ApplicationConfiguration.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/ApplicationConfiguration.java new file mode 100644 index 00000000..1a254a5b --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/ApplicationConfiguration.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.dbref; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Christoph Strobl + */ +@SpringBootApplication +class ApplicationConfiguration {} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Employee.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Employee.java new file mode 100644 index 00000000..ac9df3d2 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Employee.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.dbref; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DBRef; + +/** + * @author Christoph Strobl + */ +class Employee { + + @Id + private String id; + private String name; + + @DBRef(lazy = true) // lazy to avoid stackoverflow on load + private Manager manager; + + public Employee() { + } + + public Employee(String id, String name) { + this.id = id; + this.name = name; + } + + 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 Manager getManager() { + return manager; + } + + public void setManager(Manager manager) { + this.manager = manager; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Manager.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Manager.java new file mode 100644 index 00000000..59ec0813 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/dbref/Manager.java @@ -0,0 +1,66 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.dbref; + +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DBRef; + +/** + * @author Christoph Strobl + */ +class Manager { + + @Id // + private String id; + private String name; + + @DBRef // + private List employees; + + public Manager() { + } + + public Manager(String id, String name) { + this.id = id; + this.name = name; + } + + 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 List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/ApplicationConfiguration.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/ApplicationConfiguration.java new file mode 100644 index 00000000..bbe8830b --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/ApplicationConfiguration.java @@ -0,0 +1,26 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.jpastyle; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Christoph Strobl + */ +@SpringBootApplication +class ApplicationConfiguration { + +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Employee.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Employee.java new file mode 100644 index 00000000..e56983d3 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Employee.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.jpastyle; + +import org.springframework.data.annotation.Id; + +/** + * @author Christoph Strobl + */ +class Employee { + + @Id + private String id; + private String name; + + /** + * Only hold the id of the manager to link to it. + */ + private String managerId; + + public Employee() { + } + + public Employee(String id, String name) { + this.id = id; + this.name = name; + } + + 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 getManagerId() { + return managerId; + } + + public void setManagerId(String managerId) { + this.managerId = managerId; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Manager.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Manager.java new file mode 100644 index 00000000..e043cf24 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/jpastyle/Manager.java @@ -0,0 +1,72 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.jpastyle; + +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.ReadOnlyProperty; +import org.springframework.data.mongodb.core.mapping.DocumentReference; + +/** + * @author Christoph Strobl + */ +class Manager { + + @Id // + private String id; + private String name; + + /** + * Uses the {@literal this.id} to look up documents in the {@literal employee} collection + * that have a matching {@literal managerId} field value. + */ + @ReadOnlyProperty + @DocumentReference(lookup="{'managerId':?#{#self._id} }") + private List employees; + + public Manager() { + } + + public Manager(String id, String name) { + this.id = id; + this.name = name; + } + + 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 List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/ApplicationConfiguration.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/ApplicationConfiguration.java new file mode 100644 index 00000000..8d4d004e --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/ApplicationConfiguration.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.query; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Christoph Strobl + */ +@SpringBootApplication +class ApplicationConfiguration {} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Employee.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Employee.java new file mode 100644 index 00000000..85364791 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Employee.java @@ -0,0 +1,64 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.query; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DocumentReference; + +/** + * @author Christoph Strobl + */ +class Employee { + + @Id + private String id; + private String name; + + @DocumentReference(lazy = true) // lazy to avoid stackoverflow on load + private Manager manager; + + public Employee() { + } + + public Employee(String id, String name) { + this.id = id; + this.name = name; + } + + 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 Manager getManager() { + return manager; + } + + public void setManager(Manager manager) { + this.manager = manager; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Manager.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Manager.java new file mode 100644 index 00000000..6860574b --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/query/Manager.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.query; + +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DocumentReference; + +/** + * @author Christoph Strobl + */ +class Manager { + + @Id // + private String id; + private String name; + + /** + * Uses the value stored in the {@literal employees} field of the {@literal manager} document to look up + * documents in the {@literal employee} collection that have a matching {@literal name} field value. + */ + @DocumentReference(lookup = "{ 'name' : ?#{#target} }") // + private List employees; + + public Manager() { + } + + public Manager(String id, String name) { + this.id = id; + this.name = name; + } + + 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 List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/ApplicationConfiguration.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/ApplicationConfiguration.java new file mode 100644 index 00000000..8a728623 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/ApplicationConfiguration.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.simple; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Christoph Strobl + */ +@SpringBootApplication +class ApplicationConfiguration {} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Employee.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Employee.java new file mode 100644 index 00000000..04cb2fe0 --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Employee.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.simple; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DBRef; +import org.springframework.data.mongodb.core.mapping.DocumentReference; + +/** + * @author Christoph Strobl + */ +class Employee { + + @Id + private String id; + private String name; + + @DocumentReference(lazy = true) // lazy to avoid stackoverflow on load + private Manager manager; + + public Employee() { + } + + public Employee(String id, String name) { + this.id = id; + this.name = name; + } + + 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 Manager getManager() { + return manager; + } + + public void setManager(Manager manager) { + this.manager = manager; + } +} diff --git a/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Manager.java b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Manager.java new file mode 100644 index 00000000..c9a3aead --- /dev/null +++ b/mongodb/linking/src/main/java/example/springdata/mongodb/linking/docref/simple/Manager.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.simple; + +import java.util.List; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.DocumentReference; + +/** + * @author Christoph Strobl + */ +class Manager { + + @Id // + private String id; + private String name; + + /** + * Uses the value stored in the {@literal employees} field of the {@literal manager} document to look up + * documents in the {@literal employee} collection that have a matching {@literal _id} field value. + */ + @DocumentReference // + private List employees; + + public Manager() { + } + + public Manager(String id, String name) { + this.id = id; + this.name = name; + } + + 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 List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/mongodb/linking/src/test/java/example/springdata/mongodb/linking/dbref/DBRefTests.java b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/dbref/DBRefTests.java new file mode 100644 index 00000000..c6242800 --- /dev/null +++ b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/dbref/DBRefTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.dbref; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; + +import java.util.List; + +import com.mongodb.DBRef; +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.Update; + +/** + * @author Christoph Strobl + */ +@DataMongoTest +public class DBRefTests { + + @Autowired MongoOperations operations; + + @Test + void saveAndLoadDbRef() { + + Manager manager = new Manager("jabba-the-hutt", "jabba"); + + operations.save(manager); + + Employee employee1 = new Employee("greedo-tetsu-jr", "greedo"); + employee1.setManager(manager); + operations.save(employee1); + operations.update(Manager.class) // + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee1)) // + .first(); + + Employee employee2 = new Employee("boba-fett", "boba"); + employee2.setManager(manager); + operations.save(employee2); + operations.update(Manager.class) // + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee2)) // + .first(); + + operations.execute(Manager.class, collection -> { + + Document rawManager = collection.find(new Document("_id", manager.getId())).first(); + assertThat(rawManager.get("employees", List.class)) // + .containsExactly( // + new DBRef("employee", "greedo-tetsu-jr"), // + new DBRef("employee", "boba-fett") // + ); + return "OK"; + }); + + Manager loaded = operations.query(Manager.class) + .matching(where("id").is(manager.getId())) + .firstValue(); + + assertThat(loaded.getEmployees()) // + .allMatch(it -> it instanceof Employee) // + .extracting("name").containsExactly("greedo", "boba"); + } +} diff --git a/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/jpastyle/JpaStyleDocRefTests.java b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/jpastyle/JpaStyleDocRefTests.java new file mode 100644 index 00000000..f286d658 --- /dev/null +++ b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/jpastyle/JpaStyleDocRefTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.jpastyle; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.data.mongodb.core.MongoOperations; + +/** + * @author Christoph Strobl + */ +@DataMongoTest +public class JpaStyleDocRefTests { + + @Autowired MongoOperations operations; + + /** + * Load linked documents where where the actual reference is stored in the obverse side of the association. + */ + @Test + void saveAndLoadJpaStyleRelation() { + + Manager manager = new Manager("jabba-the-hutt", "jabba"); + + operations.save(manager); + + Employee employee1 = new Employee("greedo-tetsu-jr", "greedo"); + employee1.setManagerId(manager.getId()); // establish the link to the manager document + operations.save(employee1); + // no need to update he manager document after save of employee + + Employee employee2 = new Employee("boba-fett", "boba"); + employee2.setManagerId(manager.getId()); // establish the link to the manager document + operations.save(employee2); + // no need to update he manager document after save of employee + + operations.execute(Manager.class, collection -> { + + Document rawManager = collection.find(new Document("_id", manager.getId())).first(); + assertThat(rawManager).doesNotContainKey("employees"); + return "OK"; + }); + + Manager loaded = operations.query(Manager.class) + .matching(where("id").is(manager.getId())) + .firstValue(); + + assertThat(loaded.getEmployees()) // + .allMatch(it -> it instanceof Employee) // + .extracting("name").containsExactly("greedo", "boba"); + } +} diff --git a/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/query/QueryDocRefTests.java b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/query/QueryDocRefTests.java new file mode 100644 index 00000000..67a1110d --- /dev/null +++ b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/query/QueryDocRefTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.query; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; + +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.Update; + +/** + * @author Christoph Strobl + */ +@DataMongoTest +public class QueryDocRefTests { + + @Autowired MongoOperations operations; + + /** + * Load linked documents where where the reference is stored on the inverse and evaluated against a non id property on + * the obverse side of the association. + */ + @Test + void saveAndLoadDocRefViaQuery() { + + Manager manager = new Manager("jabba-the-hutt", "jabba"); + + operations.save(manager); + + Employee employee1 = new Employee("greedo-tetsu-jr", "greedo"); + employee1.setManager(manager); // back-link to the manager document + operations.save(employee1); + operations.update(Manager.class) // establish the link to the employee document via employee.name + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee1.getName())) // + .first(); + + Employee employee2 = new Employee("boba-fett", "boba"); + employee2.setManager(manager); // back-link to the manager document + operations.save(employee2); + operations.update(Manager.class) // establish the link to the employee document via employee.name + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee2.getName())) // + .first(); + + operations.execute(Manager.class, collection -> { + + Document rawManager = collection.find(new Document("_id", manager.getId())).first(); + assertThat(rawManager.get("employees", List.class)) // + .containsExactly("greedo", "boba"); + return "OK"; + }); + + Manager loaded = operations.query(Manager.class) + .matching(where("id").is(manager.getId())) + .firstValue(); + + assertThat(loaded.getEmployees()) // + .allMatch(it -> it instanceof Employee) // + .extracting("name").containsExactly("greedo", "boba"); + } +} diff --git a/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/simple/SimpleDocRefTests.java b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/simple/SimpleDocRefTests.java new file mode 100644 index 00000000..f01908dc --- /dev/null +++ b/mongodb/linking/src/test/java/example/springdata/mongodb/linking/docref/simple/SimpleDocRefTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.linking.docref.simple; + +import static org.assertj.core.api.Assertions.*; +import static org.springframework.data.mongodb.core.query.Criteria.*; + +import java.util.List; + +import org.bson.Document; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.query.Update; + +/** + * @author Christoph Strobl + */ +@DataMongoTest +public class SimpleDocRefTests { + + @Autowired MongoOperations operations; + + /** + * Load linked documents where where the reference is stored on the inverse and evaluated against the id property on + * the obverse side of the association. + */ + @Test + void saveAndLoadDocRef() { + + Manager manager = new Manager("jabba-the-hutt", "jabba"); + + operations.save(manager); + + Employee employee1 = new Employee("greedo-tetsu-jr", "greedo"); + employee1.setManager(manager); // back-link to the manager document + operations.save(employee1); + operations.update(Manager.class) // establish the link to the employee document via employee.id + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee1)) // + .first(); + + Employee employee2 = new Employee("boba-fett", "boba"); + employee2.setManager(manager); // back-link to the manager document + operations.save(employee2); + operations.update(Manager.class) // establish the link to the employee document via employee.id + .matching(where("id").is(manager.getId())) // + .apply(new Update().push("employees").value(employee2)) // + .first(); + + operations.execute(Manager.class, collection -> { + + Document rawManager = collection.find(new Document("_id", manager.getId())).first(); + assertThat(rawManager.get("employees", List.class)) // + .containsExactly("greedo-tetsu-jr", "boba-fett"); + return "OK"; + }); + + Manager loaded = operations.query(Manager.class) + .matching(where("id").is(manager.getId())) + .firstValue(); + + assertThat(loaded.getEmployees()) // + .allMatch(it -> it instanceof Employee) // + .extracting("name").containsExactly("greedo", "boba"); + } +} diff --git a/mongodb/linking/src/test/resources/application.properties b/mongodb/linking/src/test/resources/application.properties new file mode 100644 index 00000000..5239185a --- /dev/null +++ b/mongodb/linking/src/test/resources/application.properties @@ -0,0 +1,3 @@ +# Random port for embedded MongoDB +spring.data.mongodb.port=0 +spring.mongodb.embedded.version=3.6.0 \ No newline at end of file diff --git a/mongodb/pom.xml b/mongodb/pom.xml index ff85fcde..951bc481 100644 --- a/mongodb/pom.xml +++ b/mongodb/pom.xml @@ -33,6 +33,7 @@ transactions schema-validation querydsl + linking util