DATADOC-48 adding basic cross-store features
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user