Merge pull request #236 from alex-semenyuk/master

Introduction to Spring Data MongoDB (continue)
This commit is contained in:
Eugen 2015-08-15 14:58:41 -07:00
commit 393c1eac14
12 changed files with 230 additions and 9 deletions

View File

@ -0,0 +1,12 @@
package org.baeldung.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CascadeSave {
}

View File

@ -1,7 +1,15 @@
package org.baeldung.config;
import java.util.ArrayList;
import java.util.List;
import org.baeldung.converter.UserWriterConverter;
import org.baeldung.event.CascadeSaveMongoEventListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.convert.CustomConversions;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import com.mongodb.Mongo;
@ -11,6 +19,8 @@ import com.mongodb.MongoClient;
@EnableMongoRepositories(basePackages = "org.baeldung.repository")
public class MongoConfig extends AbstractMongoConfiguration {
private List<Converter<?, ?>> converters = new ArrayList<Converter<?, ?>>();
@Override
protected String getDatabaseName() {
return "test";
@ -25,4 +35,15 @@ public class MongoConfig extends AbstractMongoConfiguration {
public String getMappingBasePackage() {
return "org.baeldung";
}
@Bean
public CascadeSaveMongoEventListener cascadingMongoEventListener() {
return new CascadeSaveMongoEventListener();
}
@Override
public CustomConversions customConversions() {
converters.add(new UserWriterConverter());
return new CustomConversions(converters);
}
}

View File

@ -0,0 +1,25 @@
package org.baeldung.converter;
import org.springframework.stereotype.Component;
import org.baeldung.model.User;
import org.springframework.core.convert.converter.Converter;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
@Component
public class UserWriterConverter implements Converter<User, DBObject> {
@Override
public DBObject convert(User user) {
DBObject dbObject = new BasicDBObject();
dbObject.put("name", user.getName());
dbObject.put("age", user.getAge());
if (user.getEmailAddress() != null) {
DBObject emailDbObject = new BasicDBObject();
emailDbObject.put("value", user.getEmailAddress().getValue());
dbObject.put("email", emailDbObject);
}
dbObject.removeField("_class");
return dbObject;
}
}

View File

@ -0,0 +1,37 @@
package org.baeldung.event;
import org.baeldung.annotation.CascadeSave;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;
public class CascadeSaveMongoEventListener extends AbstractMongoEventListener<Object> {
@Autowired
private MongoOperations mongoOperations;
@Override
public void onBeforeConvert(final Object source) {
ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
final Object fieldValue = field.get(source);
if (fieldValue != null) {
FieldCallback callback = new FieldCallback();
ReflectionUtils.doWithFields(fieldValue.getClass(), callback);
mongoOperations.save(fieldValue);
}
}
}
});
}
}

View File

@ -0,0 +1,22 @@
package org.baeldung.event;
import java.lang.reflect.Field;
import org.springframework.data.annotation.Id;
import org.springframework.util.ReflectionUtils;
public class FieldCallback implements ReflectionUtils.FieldCallback {
private boolean idFound;
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.isAnnotationPresent(Id.class)) {
idFound = true;
}
}
public boolean isIdFound() {
return idFound;
}
}

View File

@ -0,0 +1,27 @@
package org.baeldung.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class EmailAddress {
@Id
private String id;
private String value;
public String getId() {
return id;
}
public void setId(final String id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(final String value) {
this.value = value;
}
}

View File

@ -1,7 +1,12 @@
package org.baeldung.model;
import org.baeldung.annotation.CascadeSave;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.IndexDirection;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import com.mysema.query.annotations.QueryEntity;
@ -11,9 +16,16 @@ public class User {
@Id
private String id;
@Indexed(direction = IndexDirection.ASCENDING)
private String name;
private Integer age;
@DBRef
@Field("email")
@CascadeSave
private EmailAddress emailAddress;
public String getId() {
return id;
}
@ -37,4 +49,12 @@ public class User {
public void setAge(final Integer age) {
this.age = age;
}
public EmailAddress getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(EmailAddress emailAddress) {
this.emailAddress = emailAddress;
}
}

View File

@ -10,21 +10,26 @@
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
>
<context:annotation-config/>
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
<property name="host" value="localhost"/>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongo" ref="mongo"/>
<constructor-arg ref="mongoConverter" />
<constructor-arg name="databaseName" value="test"/>
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<mongo:repositories base-package="org.baeldung.repository" mongo-template-ref="mongoTemplate"/>
<bean class="org.baeldung.event.BeforeConvertListener">
<bean class="org.baeldung.event.CascadeSaveMongoEventListener">
</bean>
<mongo:mapping-converter id="mongoConverter" base-package="org.baeldung.converter">
<mongo:custom-converters base-package="org.baeldung.converter"/>
</mongo:mapping-converter>
</beans>

View File

@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List;
import org.baeldung.config.MongoConfig;
import org.baeldung.model.EmailAddress;
import org.baeldung.model.User;
import org.junit.After;
import org.junit.Before;
@ -31,11 +32,14 @@ public class DocumentQueryIntegrationTest {
@Before
public void testSetup() {
mongoTemplate.createCollection(User.class);
if (!mongoTemplate.collectionExists(User.class)) {
mongoTemplate.createCollection(User.class);
}
}
@After
public void tearDown() {
mongoTemplate.dropCollection(EmailAddress.class);
mongoTemplate.dropCollection(User.class);
}

View File

@ -6,6 +6,7 @@ import static org.junit.Assert.assertThat;
import java.util.List;
import org.baeldung.config.MongoConfig;
import org.baeldung.model.EmailAddress;
import org.baeldung.model.User;
import org.junit.After;
import org.junit.Before;
@ -15,7 +16,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexInfo;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
@ -30,7 +34,9 @@ public class MongoTemplateQueryIntegrationTest {
@Before
public void testSetup() {
mongoTemplate.createCollection(User.class);
if (!mongoTemplate.collectionExists(User.class)) {
mongoTemplate.createCollection(User.class);
}
}
@After
@ -128,4 +134,42 @@ public class MongoTemplateQueryIntegrationTest {
List<User> users = mongoTemplate.find(query, User.class);
assertThat(users.size(), is(3));
}
@Test
public void givenUserExistsWithIndexAddedFromMapping_whenCheckingIndex_thenIndexIsExisted() {
final User user = new User();
user.setName("Brendan");
EmailAddress emailAddress = new EmailAddress();
emailAddress.setValue("a@gmail.com");
user.setEmailAddress(emailAddress);
mongoTemplate.insert(user);
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
assertThat(indexInfos.size(), is(1));
}
@Test
public void whenSavingUserWithEmailAddress_thenUserandEmailAddressSaved() {
final User user = new User();
user.setName("Brendan");
EmailAddress emailAddress = new EmailAddress();
emailAddress.setValue("b@gmail.com");
user.setEmailAddress(emailAddress);
mongoTemplate.insert(user);
assertThat(mongoTemplate.findOne(Query.query(Criteria.where("name").is("Brendan")), User.class).getEmailAddress().getValue(), is("b@gmail.com"));
}
@Test
public void givenUserExistsWithIndexAddedFromCode_whenCheckingIndex_thenIndexIsExisted() {
final User user = new User();
user.setName("Brendan");
mongoTemplate.indexOps(User.class).ensureIndex(new Index().on("name", Direction.ASC));
mongoTemplate.insert(user);
List<IndexInfo> indexInfos = mongoTemplate.indexOps("user").getIndexInfo();
assertThat(indexInfos.size(), is(2));
}
}

View File

@ -17,7 +17,9 @@ public class BaseQueryIntegrationTest {
@Before
public void testSetup() {
mongoOps.createCollection(User.class);
if (!mongoOps.collectionExists(User.class)) {
mongoOps.createCollection(User.class);
}
}
@After

View File

@ -34,7 +34,9 @@ public class UserRepositoryIntegrationTest {
@Before
public void testSetup() {
mongoOps.createCollection(User.class);
if (!mongoOps.collectionExists(User.class)) {
mongoOps.createCollection(User.class);
}
}
@After
@ -67,12 +69,11 @@ public class UserRepositoryIntegrationTest {
mongoOps.insert(user);
user = mongoOps.findOne(Query.query(Criteria.where("name").is("Jack")), User.class);
final String id = user.getId();
user.setName("Jim");
userRepository.save(user);
assertThat(mongoOps.findOne(Query.query(Criteria.where("id").is(id)), User.class).getName(), is("Jim"));
assertThat(mongoOps.findAll(User.class).size(), is(2));
}
@Test
@ -145,4 +146,5 @@ public class UserRepositoryIntegrationTest {
assertThat(users.size(), is(1));
assertThat(page.getTotalPages(), is(2));
}
}