Browse Source

DATADOC-48 adding basic cross-store features

pull/1/head
Thomas Risberg 15 years ago
parent
commit
358fd51c4d
  1. 2
      spring-data-mongodb-cross-store/.classpath
  2. 11
      spring-data-mongodb-cross-store/.settings/org.eclipse.jdt.core.prefs
  3. 120
      spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoChangeSetPersister.java
  4. 12
      spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoDocumentBacking.aj
  5. 58
      spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoEntityOperations.java
  6. 5
      spring-data-mongodb-cross-store/src/test/java/org/springframework/data/document/persistence/CrossStoreMongoTests.java
  7. 3
      spring-data-mongodb-cross-store/src/test/java/org/springframework/data/document/persistence/MongoPerson.java
  8. 27
      spring-data-mongodb-cross-store/src/test/resources/META-INF/spring/applicationContext.xml

2
spring-data-mongodb-cross-store/.classpath

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

11
spring-data-mongodb-cross-store/.settings/org.eclipse.jdt.core.prefs

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
#Mon Feb 28 16:26:01 EST 2011
#Tue Mar 01 09:48:37 EST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5
org.eclipse.jdt.core.compiler.source=1.6

120
spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoChangeSetPersister.java

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
package org.springframework.persistence.document;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.ConversionService;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.persistence.support.ChangeSet;
import org.springframework.persistence.support.ChangeSetBacked;
import org.springframework.persistence.support.ChangeSetPersister;
import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
//import edu.emory.mathcs.backport.java.util.Arrays;
public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
protected final Log log = LogFactory.getLog(getClass());
@Autowired
private DB mongoDb;
@Autowired
private ConversionService conversionService;
@Override
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, ChangeSet changeSet)
throws DataAccessException, NotFoundException {
String collection = ClassUtils.getQualifiedName(entityClass);
DBObject q = new BasicDBObject();
q.put("_id", id);
try {
DBObject dbo = mongoDb.getCollection(collection).findOne(q);
if (dbo == null) {
throw new NotFoundException();
}
String classShortName = ClassUtils.getShortName(entityClass);
for (Object property : dbo.toMap().keySet()) {
String propertyKey = (String) property;
String propertyName = propertyKey.startsWith(classShortName) ? propertyKey.substring(propertyKey.indexOf(classShortName)
+ classShortName.length() + 1) : propertyKey;
// System.err.println("Mongo persisted property [" + propertyName + "] :: " + propertyKey + " = " + dbo.get(propertyKey));
if (propertyKey.startsWith("_")) {
// Id or class
changeSet.set(propertyName, dbo.get(propertyKey));
} else {
//throw new IllegalStateException("Unknown property [" + propertyName + "] found in MongoDB store");
changeSet.set(propertyName, dbo.get(propertyKey));
}
}
} catch (MongoException ex) {
throw new DataAccessResourceFailureException("Can't read from Mongo", ex);
}
}
@Override
public Object getPersistentId(Class<? extends ChangeSetBacked> entityClass,
ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entityClass);
if (cs == null) {
return null;
}
if (cs.getValues().get(ChangeSetPersister.ID_KEY) == null) {
// Not yet persistent
return null;
}
Object o = cs.getValues().get(ChangeSetPersister.ID_KEY);
return o;
}
@Override
public Object persistState(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException {
log.info("PERSIST::"+cs);
cs.set(CLASS_KEY, entityClass.getName());
String idstr = cs.get(ID_KEY, String.class, this.conversionService);
Object id = null;
if (idstr != null) {
id = idstr;
}
if (id == null) {
log.info("Flush: entity make persistent; data store will assign id");
cs.set("_class", entityClass.getName());
String collection = entityClass.getName();
DBCollection dbc = mongoDb.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
dbc = mongoDb.createCollection(collection, dbo);
}
dbc.save(dbo);
id = dbo.get(ID_KEY);
} else {
log.info("Flush: entity already persistent with id=" + id);
String collection = entityClass.getName();
DBCollection dbc = mongoDb.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
throw new DataAccessResourceFailureException("Expected to find a collection named '" + collection +"'. It was not found, so ChangeSet can't be persisted.");
}
dbc.save(dbo);
}
return 0L;
}
private DBObject mapChangeSetToDbObject(ChangeSet cs) {
BasicDBObject dbo = new BasicDBObject();
for (String property : cs.getValues().keySet()) {
dbo.put(property, cs.getValues().get(property));
}
return dbo;
}
}

12
spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoDocumentBacking.aj

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
package org.springframework.persistence.document;
import org.springframework.persistence.support.AbstractDeferredUpdateMixinFields;
/**
* Aspect to turn an object annotated with DocumentEntity into a document entity using Mongo.
*
* @author Thomas Risberg
*/
public aspect MongoDocumentBacking extends AbstractDeferredUpdateMixinFields<DocumentEntity> {
}

58
spring-data-mongodb-cross-store/src/main/java/org/springframework/persistence/document/MongoEntityOperations.java

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
package org.springframework.persistence.document;
import java.lang.reflect.Field;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.persistence.OrderedEntityOperations;
import org.springframework.persistence.RelatedEntity;
import org.springframework.persistence.support.ChangeSetBacked;
import com.mongodb.DB;
public class MongoEntityOperations extends OrderedEntityOperations<Object, ChangeSetBacked> {
@Autowired
private DB mongoDb;
@Autowired
private MongoChangeSetPersister changeSetPersister;
@Override
public boolean cacheInEntity() {
return true;
}
@Override
public ChangeSetBacked findEntity(Class<ChangeSetBacked> entityClass, Object pk) throws DataAccessException {
throw new UnsupportedOperationException();
}
@Override
public Object findUniqueKey(ChangeSetBacked entity) throws DataAccessException {
return entity.getId();
}
@Override
public boolean isTransactional() {
// TODO
return false;
}
@Override
public boolean isTransient(ChangeSetBacked entity) throws DataAccessException {
return entity.getId() == null;
}
@Override
public Object makePersistent(Object owner, ChangeSetBacked entity, Field f, RelatedEntity fs) throws DataAccessException {
changeSetPersister.persistState(entity.getClass(), entity.getChangeSet());
return entity.getId();
}
@Override
public boolean supports(Class<?> entityClass, RelatedEntity fs) {
return entityClass.isAnnotationPresent(DocumentEntity.class);
}
}

5
spring-data-mongodb-cross-store/src/test/java/org/springframework/data/document/persistence/CrossStoreMongoTests.java

@ -19,12 +19,11 @@ public class CrossStoreMongoTests { @@ -19,12 +19,11 @@ public class CrossStoreMongoTests {
private Mongo mongo;
@Test
// @Transactional
// @Rollback(false)
@Transactional
@Rollback(false)
public void testUserConstructor() {
int age = 33;
MongoPerson p = new MongoPerson("Thomas", age);
//Assert.assertEquals(p.getRedisValue().getString("RedisPerson.name"), p.getName());
Assert.assertEquals(age, p.getAge());
p.birthday();
Assert.assertEquals(1 + age, p.getAge());

3
spring-data-mongodb-cross-store/src/test/java/org/springframework/data/document/persistence/MongoPerson.java

@ -1,8 +1,11 @@ @@ -1,8 +1,11 @@
package org.springframework.data.document.persistence;
import javax.persistence.Entity;
import org.springframework.persistence.RelatedEntity;
import org.springframework.persistence.document.DocumentEntity;
@Entity
@DocumentEntity
public class MongoPerson {

27
spring-data-mongodb-cross-store/src/test/resources/META-INF/spring/applicationContext.xml

@ -1,7 +1,9 @@ @@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost" />
@ -16,4 +18,27 @@ @@ -16,4 +18,27 @@
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator" />
<!-- Mongo aspect config -->
<bean class="org.springframework.persistence.document.MongoDocumentBacking"
factory-method="aspectOf">
<property name="changeSetConfiguration" ref="mongoChangeSetConfiguration"/>
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>

Loading…
Cancel
Save