Skip to content

Commit 393c1ea

Browse files
author
Eugen
committed
Merge pull request eugenp#236 from alex-semenyuk/master
Introduction to Spring Data MongoDB (continue)
2 parents 7243b16 + 4f55bef commit 393c1ea

File tree

12 files changed

+230
-9
lines changed

12 files changed

+230
-9
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.baeldung.annotation;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target(ElementType.FIELD)
10+
public @interface CascadeSave {
11+
12+
}

spring-data-mongodb/src/main/java/org/baeldung/config/MongoConfig.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package org.baeldung.config;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.baeldung.converter.UserWriterConverter;
7+
import org.baeldung.event.CascadeSaveMongoEventListener;
8+
import org.springframework.context.annotation.Bean;
39
import org.springframework.context.annotation.Configuration;
410
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
11+
import org.springframework.data.mongodb.core.convert.CustomConversions;
12+
import org.springframework.core.convert.converter.Converter;
513
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
614

715
import com.mongodb.Mongo;
@@ -11,6 +19,8 @@
1119
@EnableMongoRepositories(basePackages = "org.baeldung.repository")
1220
public class MongoConfig extends AbstractMongoConfiguration {
1321

22+
private List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
23+
1424
@Override
1525
protected String getDatabaseName() {
1626
return "test";
@@ -25,4 +35,15 @@ public Mongo mongo() throws Exception {
2535
public String getMappingBasePackage() {
2636
return "org.baeldung";
2737
}
38+
39+
@Bean
40+
public CascadeSaveMongoEventListener cascadingMongoEventListener() {
41+
return new CascadeSaveMongoEventListener();
42+
}
43+
44+
@Override
45+
public CustomConversions customConversions() {
46+
converters.add(new UserWriterConverter());
47+
return new CustomConversions(converters);
48+
}
2849
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.baeldung.converter;
2+
3+
import org.springframework.stereotype.Component;
4+
import org.baeldung.model.User;
5+
import org.springframework.core.convert.converter.Converter;
6+
7+
import com.mongodb.BasicDBObject;
8+
import com.mongodb.DBObject;
9+
10+
@Component
11+
public class UserWriterConverter implements Converter<User, DBObject> {
12+
@Override
13+
public DBObject convert(User user) {
14+
DBObject dbObject = new BasicDBObject();
15+
dbObject.put("name", user.getName());
16+
dbObject.put("age", user.getAge());
17+
if (user.getEmailAddress() != null) {
18+
DBObject emailDbObject = new BasicDBObject();
19+
emailDbObject.put("value", user.getEmailAddress().getValue());
20+
dbObject.put("email", emailDbObject);
21+
}
22+
dbObject.removeField("_class");
23+
return dbObject;
24+
}
25+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.baeldung.event;
2+
3+
import org.baeldung.annotation.CascadeSave;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.data.mongodb.core.MongoOperations;
6+
import org.springframework.data.mongodb.core.mapping.DBRef;
7+
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
8+
import org.springframework.util.ReflectionUtils;
9+
10+
import java.lang.reflect.Field;
11+
12+
public class CascadeSaveMongoEventListener extends AbstractMongoEventListener<Object> {
13+
@Autowired
14+
private MongoOperations mongoOperations;
15+
16+
@Override
17+
public void onBeforeConvert(final Object source) {
18+
ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
19+
20+
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
21+
ReflectionUtils.makeAccessible(field);
22+
23+
if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
24+
final Object fieldValue = field.get(source);
25+
26+
if (fieldValue != null) {
27+
FieldCallback callback = new FieldCallback();
28+
29+
ReflectionUtils.doWithFields(fieldValue.getClass(), callback);
30+
31+
mongoOperations.save(fieldValue);
32+
}
33+
}
34+
}
35+
});
36+
}
37+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.baeldung.event;
2+
3+
import java.lang.reflect.Field;
4+
5+
import org.springframework.data.annotation.Id;
6+
import org.springframework.util.ReflectionUtils;
7+
8+
public class FieldCallback implements ReflectionUtils.FieldCallback {
9+
private boolean idFound;
10+
11+
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
12+
ReflectionUtils.makeAccessible(field);
13+
14+
if (field.isAnnotationPresent(Id.class)) {
15+
idFound = true;
16+
}
17+
}
18+
19+
public boolean isIdFound() {
20+
return idFound;
21+
}
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.baeldung.model;
2+
3+
import org.springframework.data.annotation.Id;
4+
import org.springframework.data.mongodb.core.mapping.Document;
5+
6+
@Document
7+
public class EmailAddress {
8+
@Id
9+
private String id;
10+
private String value;
11+
12+
public String getId() {
13+
return id;
14+
}
15+
16+
public void setId(final String id) {
17+
this.id = id;
18+
}
19+
20+
public String getValue() {
21+
return value;
22+
}
23+
24+
public void setValue(final String value) {
25+
this.value = value;
26+
}
27+
}

spring-data-mongodb/src/main/java/org/baeldung/model/User.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package org.baeldung.model;
22

3+
import org.baeldung.annotation.CascadeSave;
34
import org.springframework.data.annotation.Id;
5+
import org.springframework.data.mongodb.core.index.IndexDirection;
6+
import org.springframework.data.mongodb.core.index.Indexed;
7+
import org.springframework.data.mongodb.core.mapping.DBRef;
48
import org.springframework.data.mongodb.core.mapping.Document;
9+
import org.springframework.data.mongodb.core.mapping.Field;
510

611
import com.mysema.query.annotations.QueryEntity;
712

@@ -11,9 +16,16 @@ public class User {
1116

1217
@Id
1318
private String id;
19+
@Indexed(direction = IndexDirection.ASCENDING)
1420
private String name;
21+
1522
private Integer age;
1623

24+
@DBRef
25+
@Field("email")
26+
@CascadeSave
27+
private EmailAddress emailAddress;
28+
1729
public String getId() {
1830
return id;
1931
}
@@ -37,4 +49,12 @@ public Integer getAge() {
3749
public void setAge(final Integer age) {
3850
this.age = age;
3951
}
52+
53+
public EmailAddress getEmailAddress() {
54+
return emailAddress;
55+
}
56+
57+
public void setEmailAddress(EmailAddress emailAddress) {
58+
this.emailAddress = emailAddress;
59+
}
4060
}

spring-data-mongodb/src/main/resources/mongoConfig.xml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,26 @@
1010
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
1111
>
1212
<context:annotation-config/>
13-
13+
1414
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
1515
<property name="host" value="localhost"/>
1616
</bean>
1717

1818
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
1919
<constructor-arg name="mongo" ref="mongo"/>
20+
<constructor-arg ref="mongoConverter" />
2021
<constructor-arg name="databaseName" value="test"/>
2122
</bean>
2223

2324
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
2425

2526
<mongo:repositories base-package="org.baeldung.repository" mongo-template-ref="mongoTemplate"/>
26-
27-
<bean class="org.baeldung.event.BeforeConvertListener">
27+
28+
<bean class="org.baeldung.event.CascadeSaveMongoEventListener">
2829
</bean>
2930

31+
<mongo:mapping-converter id="mongoConverter" base-package="org.baeldung.converter">
32+
<mongo:custom-converters base-package="org.baeldung.converter"/>
33+
</mongo:mapping-converter>
34+
3035
</beans>

spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/DocumentQueryIntegrationTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.List;
88

99
import org.baeldung.config.MongoConfig;
10+
import org.baeldung.model.EmailAddress;
1011
import org.baeldung.model.User;
1112
import org.junit.After;
1213
import org.junit.Before;
@@ -31,11 +32,14 @@ public class DocumentQueryIntegrationTest {
3132

3233
@Before
3334
public void testSetup() {
34-
mongoTemplate.createCollection(User.class);
35+
if (!mongoTemplate.collectionExists(User.class)) {
36+
mongoTemplate.createCollection(User.class);
37+
}
3538
}
3639

3740
@After
3841
public void tearDown() {
42+
mongoTemplate.dropCollection(EmailAddress.class);
3943
mongoTemplate.dropCollection(User.class);
4044
}
4145

spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/MongoTemplateQueryIntegrationTest.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.List;
77

88
import org.baeldung.config.MongoConfig;
9+
import org.baeldung.model.EmailAddress;
910
import org.baeldung.model.User;
1011
import org.junit.After;
1112
import org.junit.Before;
@@ -15,7 +16,10 @@
1516
import org.springframework.data.domain.PageRequest;
1617
import org.springframework.data.domain.Pageable;
1718
import org.springframework.data.domain.Sort;
19+
import org.springframework.data.domain.Sort.Direction;
1820
import org.springframework.data.mongodb.core.MongoTemplate;
21+
import org.springframework.data.mongodb.core.index.Index;
22+
import org.springframework.data.mongodb.core.index.IndexInfo;
1923
import org.springframework.data.mongodb.core.query.Criteria;
2024
import org.springframework.data.mongodb.core.query.Query;
2125
import org.springframework.test.context.ContextConfiguration;
@@ -30,7 +34,9 @@ public class MongoTemplateQueryIntegrationTest {
3034

3135
@Before
3236
public void testSetup() {
33-
mongoTemplate.createCollection(User.class);
37+
if (!mongoTemplate.collectionExists(User.class)) {
38+
mongoTemplate.createCollection(User.class);
39+
}
3440
}
3541

3642
@After
@@ -128,4 +134,42 @@ public void givenUsersExist_whenFindingUsersAndSortThem_thenUsersAreFoundAndSort
128134
List<User> users = mongoTemplate.find(query, User.class);
129135
assertThat(users.size(), is(3));
130136
}
137+
138+
@Test
139+
public void givenUserExistsWithIndexAddedFromMapping_whenCheckingIndex_thenIndexIsExisted() {
140+
final User user = new User();
141+
user.setName("Brendan");
142+
EmailAddress emailAddress = new EmailAddress();
143+
emailAddress.setValue("[email protected]");
144+
user.setEmailAddress(emailAddress);
145+
mongoTemplate.insert(user);
146+
147+
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
148+
149+
assertThat(indexInfos.size(), is(1));
150+
}
151+
152+
@Test
153+
public void whenSavingUserWithEmailAddress_thenUserandEmailAddressSaved() {
154+
final User user = new User();
155+
user.setName("Brendan");
156+
EmailAddress emailAddress = new EmailAddress();
157+
emailAddress.setValue("[email protected]");
158+
user.setEmailAddress(emailAddress);
159+
mongoTemplate.insert(user);
160+
161+
assertThat(mongoTemplate.findOne(Query.query(Criteria.where("name").is("Brendan")), User.class).getEmailAddress().getValue(), is("[email protected]"));
162+
}
163+
164+
@Test
165+
public void givenUserExistsWithIndexAddedFromCode_whenCheckingIndex_thenIndexIsExisted() {
166+
final User user = new User();
167+
user.setName("Brendan");
168+
mongoTemplate.indexOps(User.class).ensureIndex(new Index().on("name", Direction.ASC));
169+
mongoTemplate.insert(user);
170+
171+
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
172+
173+
assertThat(indexInfos.size(), is(2));
174+
}
131175
}

0 commit comments

Comments
 (0)