Merge branch 'master' of github.com:SpringSource/spring-data-document

This commit is contained in:
J. Brisbin
2011-03-29 11:26:51 -05:00
15 changed files with 187 additions and 127 deletions

View File

@@ -10,9 +10,9 @@
<modules>
<module>spring-data-document-parent</module>
<module>spring-data-document-core</module>
<module>spring-data-mongo-log4j</module>
<module>spring-data-mongodb</module>
<module>spring-data-mongodb-cross-store</module>
<module>spring-data-mongodb-log4j</module>
<module>spring-data-couchdb</module>
</modules>

View File

@@ -307,6 +307,14 @@
<showDeprecation>false</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<useDefaultManifestFile>true</useDefaultManifestFile>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>

View File

@@ -26,7 +26,7 @@ public class DocumentBackedTransactionSynchronization implements TransactionSync
@Override
public void afterCommit() {
log.debug("After Commit called for " + entity);
changeSetPersister.persistState(entity.getClass(), entity.getChangeSet());
changeSetPersister.persistState(entity, entity.getChangeSet());
changeSetTxStatus = 0;
}

View File

@@ -1,5 +1,7 @@
package org.springframework.data.persistence.document.mongo;
import javax.persistence.EntityManagerFactory;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
@@ -7,6 +9,7 @@ import com.mongodb.MongoException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.document.mongodb.CollectionCallback;
import org.springframework.data.document.mongodb.MongoTemplate;
@@ -29,14 +32,27 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
private MongoTemplate mongoTemplate;
private EntityManagerFactory entityManagerFactory;
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
@Override
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass,
Object id, final ChangeSet changeSet) throws DataAccessException,
NotFoundException {
Object id, final ChangeSet changeSet)
throws DataAccessException, NotFoundException {
if (id == null) {
log.debug("Unable to load MongoDB data for null id");
return;
}
String collName = getCollectionNameForEntity(entityClass);
final DBObject dbk = new BasicDBObject();
@@ -75,26 +91,20 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
}
@Override
public Object getPersistentId(Class<? extends ChangeSetBacked> entityClass,
ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entityClass);
if (cs == null) {
return null;
public Object getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entity);
if (entityManagerFactory == null) {
throw new DataAccessResourceFailureException("EntityManagerFactory cannot be null");
}
if (cs.getValues().get(ChangeSetPersister.ID_KEY) == null) {
// Not yet persistent
return null;
}
Object o = cs.getValues().get(ChangeSetPersister.ID_KEY);
Object o = entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
return o;
}
@Override
public Object persistState(Class<? extends ChangeSetBacked> entityClass,
ChangeSet cs) throws DataAccessException {
public Object persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException {
log.debug("Flush: changeset: " + cs.getValues().keySet());
String collName = getCollectionNameForEntity(entityClass);
String collName = getCollectionNameForEntity(entity.getClass());
DBCollection dbc = mongoTemplate.getCollection(collName);
if (dbc == null) {
dbc = mongoTemplate.createCollection(collName);
@@ -103,8 +113,8 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
if (key != null && !key.startsWith("_") && !key.equals(ChangeSetPersister.ID_KEY)) {
Object value = cs.getValues().get(key);
final DBObject dbQuery = new BasicDBObject();
dbQuery.put(ENTITY_ID, cs.getValues().get(ChangeSetPersister.ID_KEY));
dbQuery.put(ENTITY_CLASS, entityClass.getName());
dbQuery.put(ENTITY_ID, getPersistentId(entity, cs));
dbQuery.put(ENTITY_CLASS, entity.getClass().getName());
dbQuery.put(ENTITY_FIELD_NAME, key);
dbQuery.put(ENTITY_FIELD_CLASS, value.getClass().getName());
DBObject dbId = mongoTemplate.execute(collName,
@@ -134,8 +144,7 @@ public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
return 0L;
}
private String getCollectionNameForEntity(
Class<? extends ChangeSetBacked> entityClass) {
private String getCollectionNameForEntity(Class<? extends ChangeSetBacked> entityClass) {
return ClassUtils.getQualifiedName(entityClass);
}

View File

@@ -76,11 +76,11 @@ public aspect MongoDocumentBacking {
args(newVal) &&
!set(* DocumentBacked.*);
protected pointcut entityIdSet(DocumentBacked entity, Object newVal) :
set(@Id * DocumentBacked+.*) &&
this(entity) &&
args(newVal) &&
!set(* DocumentBacked.*);
// protected pointcut entityIdSet(DocumentBacked entity, Object newVal) :
// set(@Id * DocumentBacked+.*) &&
// this(entity) &&
// args(newVal) &&
// !set(* DocumentBacked.*);
before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) {
LOGGER
@@ -118,12 +118,12 @@ public aspect MongoDocumentBacking {
// Flush the entity state to the persistent store
public void DocumentBacked.flush() {
itdChangeSetPersister.persistState(this.getClass(), this.changeSet);
Object id = itdChangeSetPersister.getPersistentId(this, this.changeSet);
itdChangeSetPersister.persistState(this, this.changeSet);
}
public Object DocumentBacked.get_persistent_id() {
return itdChangeSetPersister.getPersistentId(this.getClass(),
this.changeSet);
return itdChangeSetPersister.getPersistentId(this, this.changeSet);
}
/**
@@ -160,17 +160,17 @@ public aspect MongoDocumentBacking {
return proceed(entity, newVal);
}
/**
* delegates field writes to the state accessors instance
*/
Object around(DocumentBacked entity, Object newVal) : entityIdSet(entity, newVal) {
Field f = field(thisJoinPoint);
String propName = f.getName();
LOGGER.trace("SET @Id -> ChangeSet @Id property [" + propName
+ "] with value=[" + newVal + "]");
entity.getChangeSet().set("_id", newVal);
return proceed(entity, newVal);
}
// /**
// * delegates field writes to the state accessors instance
// */
// Object around(DocumentBacked entity, Object newVal) : entityIdSet(entity, newVal) {
// Field f = field(thisJoinPoint);
// String propName = f.getName();
// LOGGER.trace("SET @Id -> ChangeSet @Id property [" + propName
// + "] with value=[" + newVal + "]");
// entity.getChangeSet().set("_id", newVal);
// return proceed(entity, newVal);
// }
Field field(JoinPoint joinPoint) {
FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();

View File

@@ -64,11 +64,6 @@ public class CrossStoreMongoTests {
public void testReadJpaToMongoEntityRelationship() {
Person found = entityManager.find(Person.class, 1L);
Assert.assertNotNull(found);
// TODO: This part isn't quite working yet - need to intercept the id
// population from JPA EM
found.setId(found.getId());
Assert.assertEquals(Long.valueOf(1), found.getId());
Assert.assertNotNull(found);
Assert.assertEquals(Long.valueOf(1), found.getId());
@@ -84,11 +79,6 @@ public class CrossStoreMongoTests {
public void testUpdatedJpaToMongoEntityRelationship() {
Person found = entityManager.find(Person.class, 1L);
Assert.assertNotNull(found);
// TODO: This part isn't quite working yet - need to intercept the id
// population from JPA EM
found.setId(found.getId());
Assert.assertEquals(Long.valueOf(1), found.getId());
Assert.assertNotNull(found);
Assert.assertEquals(Long.valueOf(1), found.getId());

View File

@@ -1,66 +0,0 @@
package org.springframework.persistence.document.test;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Account {
@Id
private Long id;
private String name;
private float balance;
private String friendlyName;
private String whatever;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getBalance() {
return balance;
}
public void setBalance(float balance) {
this.balance = balance;
}
public String getFriendlyName() {
return friendlyName;
}
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
public String getWhatever() {
return whatever;
}
public void setWhatever(String whatever) {
this.whatever = whatever;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", balance=" + balance
+ ", friendlyName=" + friendlyName + "]";
}
}

View File

@@ -4,7 +4,7 @@
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.springframework.persistence.document.test.Account</class>
<class>org.springframework.persistence.document.test.Person</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<!--value='create' to build a new database on each run; value='update' to modify an existing database; value='create-drop' means the same as 'create' but also drops tables when Hibernate closes; value='validate' makes no changes to the database-->

View File

@@ -36,6 +36,7 @@
<bean id="mongoChangeSetPersister"
class="org.springframework.data.persistence.document.mongo.MongoChangeSetPersister">
<property name="mongoTemplate" ref="mongoTemplate"/>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<jdbc:embedded-database id="dataSource" type="HSQL">

View File

@@ -641,7 +641,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
public <T> void save(String collectionName, T objectToSave, MongoWriter<T> writer) {
BasicDBObject dbDoc = new BasicDBObject();
writer.write(objectToSave, dbDoc);
ObjectId id = saveDBObject(collectionName, dbDoc);
Object id = saveDBObject(collectionName, dbDoc);
populateIdIfNecessary(objectToSave, id);
if (null != applicationContext) {
eventQueue.add(new SaveEvent(collectionName, dbDoc));
@@ -697,20 +697,20 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return ids;
}
protected ObjectId saveDBObject(String collectionName, final DBObject dbDoc) {
protected Object saveDBObject(String collectionName, final DBObject dbDoc) {
if (dbDoc.keySet().isEmpty()) {
return null;
}
return execute(collectionName, new CollectionCallback<ObjectId>() {
public ObjectId doInCollection(DBCollection collection) throws MongoException, DataAccessException {
return execute(collectionName, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
if (writeConcern == null) {
collection.save(dbDoc);
} else {
collection.save(dbDoc, writeConcern);
}
return (ObjectId) dbDoc.get(ID);
return dbDoc.get(ID);
}
});
}

View File

@@ -26,6 +26,8 @@ import org.springframework.data.document.InvalidDocumentStoreApiUsageException;
public class Criteria implements CriteriaDefinition {
private String key;
private List<Criteria> criteriaChain;
private LinkedHashMap<String, Object> criteria = new LinkedHashMap<String, Object>();
@@ -33,9 +35,16 @@ public class Criteria implements CriteriaDefinition {
public Criteria(String key) {
this.criteriaChain = new ArrayList<Criteria>();
this.criteriaChain.add(this);
this.key = key;
}
protected Criteria(List<Criteria> criteriaChain, String key) {
this.criteriaChain = criteriaChain;
this.criteriaChain.add(this);
this.key = key;
}
/**
* Static factory method to create a Criteria using the provided key
@@ -47,6 +56,16 @@ public class Criteria implements CriteriaDefinition {
return new Criteria(key);
}
/**
* Static factory method to create a Criteria using the provided key
*
* @param key
* @return
*/
public Criteria and(String key) {
return new Criteria(this.criteriaChain, key);
}
/**
* Creates a criterion using the $is operator
*
@@ -207,6 +226,16 @@ public class Criteria implements CriteriaDefinition {
return this;
}
/**
* Creates a criterion using the $elemMatch operator
*
* @param t
* @return
*/
public Criteria elemMatch(Criteria c) {
criteria.put("$elemMatch", c.getCriteriaObject());
return this;
}
/**
* Creates an or query using the $or operator for all of the provided queries
*
@@ -224,6 +253,19 @@ public class Criteria implements CriteriaDefinition {
* @see org.springframework.datastore.document.mongodb.query.Criteria#getCriteriaObject(java.lang.String)
*/
public DBObject getCriteriaObject() {
if (this.criteriaChain.size() == 1) {
return criteriaChain.get(0).getSingleCriteriaObject();
}
else {
DBObject criteriaObject = new BasicDBObject();
for (Criteria c : this.criteriaChain) {
criteriaObject.putAll(c.getSingleCriteriaObject());
}
return criteriaObject;
}
}
protected DBObject getSingleCriteriaObject() {
DBObject dbo = new BasicDBObject();
boolean not = false;
for (String k : this.criteria.keySet()) {

View File

@@ -127,7 +127,10 @@ public class MongoTemplateTests {
PersonWithIdPropertyOfTypeString p1 = new PersonWithIdPropertyOfTypeString();
p1.setFirstName("Sven_1");
p1.setAge(22);
// insert
template.insert(p1);
// also try save
template.save(p1);
assertThat(p1.getId(), notNullValue());
PersonWithIdPropertyOfTypeString p1q = template.findOne(new Query(where("id").is(p1.getId())), PersonWithIdPropertyOfTypeString.class);
assertThat(p1q, notNullValue());
@@ -137,7 +140,10 @@ public class MongoTemplateTests {
p2.setFirstName("Sven_2");
p2.setAge(22);
p2.setId("TWO");
// insert
template.insert(p2);
// also try save
template.save(p2);
assertThat(p2.getId(), notNullValue());
PersonWithIdPropertyOfTypeString p2q = template.findOne(new Query(where("id").is(p2.getId())), PersonWithIdPropertyOfTypeString.class);
assertThat(p2q, notNullValue());
@@ -146,7 +152,10 @@ public class MongoTemplateTests {
PersonWith_idPropertyOfTypeString p3 = new PersonWith_idPropertyOfTypeString();
p3.setFirstName("Sven_3");
p3.setAge(22);
// insert
template.insert(p3);
// also try save
template.save(p3);
assertThat(p3.get_id(), notNullValue());
PersonWith_idPropertyOfTypeString p3q = template.findOne(new Query(where("_id").is(p3.get_id())), PersonWith_idPropertyOfTypeString.class);
assertThat(p3q, notNullValue());
@@ -155,8 +164,11 @@ public class MongoTemplateTests {
PersonWith_idPropertyOfTypeString p4 = new PersonWith_idPropertyOfTypeString();
p4.setFirstName("Sven_4");
p4.setAge(22);
p4.set_id("FOUR");
p4.set_id("FOUR");
// insert
template.insert(p4);
// also try save
template.save(p4);
assertThat(p4.get_id(), notNullValue());
PersonWith_idPropertyOfTypeString p4q = template.findOne(new Query(where("_id").is(p4.get_id())), PersonWith_idPropertyOfTypeString.class);
assertThat(p4q, notNullValue());
@@ -165,7 +177,10 @@ public class MongoTemplateTests {
PersonWithIdPropertyOfTypeObjectId p5 = new PersonWithIdPropertyOfTypeObjectId();
p5.setFirstName("Sven_5");
p5.setAge(22);
// insert
template.insert(p5);
// also try save
template.save(p5);
assertThat(p5.getId(), notNullValue());
PersonWithIdPropertyOfTypeObjectId p5q = template.findOne(new Query(where("id").is(p5.getId())), PersonWithIdPropertyOfTypeObjectId.class);
assertThat(p5q, notNullValue());
@@ -175,8 +190,11 @@ public class MongoTemplateTests {
p6.setFirstName("Sven_6");
p6.setAge(22);
p6.setId(new ObjectId());
// insert
template.insert(p6);
assertThat(p6.getId(), notNullValue());
// also try save
template.save(p6);
assertThat(p6.getId(), notNullValue());
PersonWithIdPropertyOfTypeObjectId p6q = template.findOne(new Query(where("id").is(p6.getId())), PersonWithIdPropertyOfTypeObjectId.class);
assertThat(p6q, notNullValue());
assertThat(p6q.getId(), is(p6.getId()));
@@ -184,8 +202,11 @@ public class MongoTemplateTests {
PersonWith_idPropertyOfTypeObjectId p7 = new PersonWith_idPropertyOfTypeObjectId();
p7.setFirstName("Sven_7");
p7.setAge(22);
// insert
template.insert(p7);
assertThat(p7.get_id(), notNullValue());
// also try save
template.save(p7);
assertThat(p7.get_id(), notNullValue());
PersonWith_idPropertyOfTypeObjectId p7q = template.findOne(new Query(where("_id").is(p7.get_id())), PersonWith_idPropertyOfTypeObjectId.class);
assertThat(p7q, notNullValue());
assertThat(p7q.get_id(), is(p7.get_id()));
@@ -194,7 +215,10 @@ public class MongoTemplateTests {
p8.setFirstName("Sven_8");
p8.setAge(22);
p8.set_id(new ObjectId());
// insert
template.insert(p8);
// also try save
template.save(p8);
assertThat(p8.get_id(), notNullValue());
PersonWith_idPropertyOfTypeObjectId p8q = template.findOne(new Query(where("_id").is(p8.get_id())), PersonWith_idPropertyOfTypeObjectId.class);
assertThat(p8q, notNullValue());

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2010-2011 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
*
* http://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 org.springframework.data.document.mongodb.query;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.data.document.mongodb.query.Index.Duplicates;
public class CriteriaTests {
@Test
public void testSimpleCriteria() {
Criteria c = new Criteria("name").is("Bubba");
Assert.assertEquals("{ \"name\" : \"Bubba\"}", c.getCriteriaObject().toString());
}
@Test
public void testChainedCriteria() {
Criteria c = new Criteria("name").is("Bubba").and("age").lt(21);
Assert.assertEquals("{ \"name\" : \"Bubba\" , \"age\" : { \"$lt\" : 21}}", c.getCriteriaObject().toString());
}
}

View File

@@ -29,6 +29,13 @@ public class QueryTests {
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testSimpleQueryWithChainedCriteria() {
Query q = new Query(where("name").is("Thomas").and("age").lt(80));
String expected = "{ \"name\" : \"Thomas\" , \"age\" : { \"$lt\" : 80}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testQueryWithNot() {
Query q = new Query(where("name").is("Thomas")).and(where("age").not().mod(10, 0));
@@ -74,4 +81,10 @@ public class QueryTests {
Assert.assertEquals(expected, q.getQueryObject().toString());
}
@Test
public void testQueryWithElemMatch() {
Query q = new Query(where("openingHours").elemMatch(where("dayOfWeek").is("Monday").and("open").lte("1800")));
String expected = "{ \"openingHours\" : { \"$elemMatch\" : { \"dayOfWeek\" : \"Monday\" , \"open\" : { \"$lte\" : \"1800\"}}}}";
Assert.assertEquals(expected, q.getQueryObject().toString());
}
}

View File

@@ -44,7 +44,9 @@
<includes>
<include>org.springframework.data:spring-data-document-core</include>
<include>org.springframework.data:spring-data-mongodb</include>
<include>org.springframework.data:spring-data-couchdb</include>
<include>org.springframework.data:spring-data-mongodb-cross-store</include>
<include>org.springframework.data:spring-data-mongodb-log4j</include>
<!-- <include>org.springframework.data:spring-data-couchdb</include> -->
</includes>
<binaries>
<outputDirectory>dist</outputDirectory>
@@ -57,8 +59,10 @@
see pom.xml 'maven-source-plugin' declaration -->
<includes>
<include>org.springframework.data:spring-data-document-core</include>
<!-- <include>org.springframework.data:spring-data-couchdb</include> -->
<include>org.springframework.data:spring-data-mongodb</include>
<include>org.springframework.data:spring-data-mongodb-cross-store</include>
<include>org.springframework.data:spring-data-mongodb-log4j</include>
<!-- <include>org.springframework.data:spring-data-couchdb</include> -->
</includes>
<binaries>
<attachmentClassifier>sources</attachmentClassifier>