From 486b9a0e1db8dc1977d70a74902c5f571474d1a2 Mon Sep 17 00:00:00 2001 From: Thomas Risberg Date: Fri, 8 Apr 2011 00:54:33 -0400 Subject: [PATCH 1/2] some additional cross-store docs --- src/docbkx/reference/cross-store.xml | 64 ++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 9 deletions(-) diff --git a/src/docbkx/reference/cross-store.xml b/src/docbkx/reference/cross-store.xml index 94251a596..66087dede 100644 --- a/src/docbkx/reference/cross-store.xml +++ b/src/docbkx/reference/cross-store.xml @@ -191,11 +191,12 @@ persisted in MongoDB should be annotated using the @RelatedDocument annotation. Well, that is really all you need to do. The cross-store aspects take care of the rest. This - include marking the field with @Transient so it won't be persisted using - JPA, keeping track of any changes and flushing them on succesfull - transaction completion, loading teh document for MongoDB when the values - is used in your application. Here is an example of a simple Entity that - has a field annotated with @RelatedEntity. + includes marking the field with @Transient so it won't be persisted using + JPA, keeping track of any changes made to the field value and writing them + to the database on succesfull transaction completion, loading teh document + from MongoDB the first time the value is used in your application. Here is + an example of a simple Entity that has a field annotated with + @RelatedEntity. Example of Entity with @RelatedDocument @@ -226,6 +227,14 @@ public class Customer { private Map<String, String> questionsAndAnswers; + public SurveyInfo() { + this.questionsAndAnswers = new HashMap<String, String>(); + } + + public SurveyInfo(Map<String, String> questionsAndAnswers) { + this.questionsAndAnswers = questionsAndAnswers; + } + public Map<String, String> getQuestionsAndAnswers() { return questionsAndAnswers; } @@ -233,14 +242,51 @@ public class Customer { public void setQuestionsAndAnswers(Map<String, String> questionsAndAnswers) { this.questionsAndAnswers = questionsAndAnswers; } -} + + public SurveyInfo addQuestionAndAnswer(String question, String answer) { + this.questionsAndAnswers.put(question, answer); + return this; + } +} - Once t... + Once the SurveyInfo has been set on the Customer object above the + MongoTemplate that was configured above is used to save the SurveyInfo + along with some metadata about the JPA Entity is stored in a MongoDB + collection named after the fully qualified name of the JPA Entity class. + The following code: - + + Example of code using the JPA Entity configured for cross-store + persistence + + Customer customer = new Customer(); + customer.setFirstName("Sven"); + customer.setLastName("Olafsen"); + SurveyInfo surveyInfo = new SurveyInfo() + .addQuestionAndAnswer("age", "22") + .addQuestionAndAnswer("married", "Yes") + .addQuestionAndAnswer("citizenship", "Norwegian"); + customer.setSurveyInfo(surveyInfo); + customerRepository.save(customer); + + - + Executing the code above results in the following JSON document + stored in MongoDB. + + + Example of JSON document stored in MongoDB + + { "_id" : ObjectId( "4d9e8b6e3c55287f87d4b79e" ), + "_entity_id" : 1, + "_entity_class" : "org.springframework.data.mongodb.examples.custsvc.domain.Customer", + "_entity_field_name" : "surveyInfo", + "questionsAndAnswers" : { "married" : "Yes", + "age" : "22", + "citizenship" : "Norwegian" }, + "_entity_field_class" : "org.springframework.data.mongodb.examples.custsvc.domain.SurveyInfo" } + From 76b9922e35d9df652c7b6a94dd271b940d44ad52 Mon Sep 17 00:00:00 2001 From: Thomas Risberg Date: Fri, 8 Apr 2011 00:55:36 -0400 Subject: [PATCH 2/2] DATADOC-48 moved clearing change-set values to postRemove lifecycle --- .../document/mongo/MongoDocumentBacking.aj | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/spring-data-mongodb-cross-store/src/main/java/org/springframework/data/persistence/document/mongo/MongoDocumentBacking.aj b/spring-data-mongodb-cross-store/src/main/java/org/springframework/data/persistence/document/mongo/MongoDocumentBacking.aj index d14db1b50..e99fb0325 100644 --- a/spring-data-mongodb-cross-store/src/main/java/org/springframework/data/persistence/document/mongo/MongoDocumentBacking.aj +++ b/spring-data-mongodb-cross-store/src/main/java/org/springframework/data/persistence/document/mongo/MongoDocumentBacking.aj @@ -82,10 +82,10 @@ public aspect MongoDocumentBacking { args(entity); // intercept EntityManager.remove calls - public pointcut entityManagerRemove(EntityManager em, Object entity) : - call(* EntityManager.remove(Object)) && - target(em) && - args(entity); +// public pointcut entityManagerRemove(EntityManager em, Object entity) : +// call(* EntityManager.remove(Object)) && +// target(em) && +// args(entity); // move changeSet from detached entity to the newly merged persistent object Object around(EntityManager em, Object entity) : entityManagerMerge(em, entity) { @@ -97,26 +97,31 @@ public aspect MongoDocumentBacking { } // clear changeSet from removed entity - Object around(EntityManager em, Object entity) : entityManagerRemove(em, entity) { - if (entity instanceof DocumentBacked) { - ChangeSet nulledCs = new HashMapChangeSet(); - DocumentBacked documentEntity = (DocumentBacked) entity; - @SuppressWarnings("unchecked") - ChangeSetPersister changeSetPersister = (ChangeSetPersister)documentEntity.itdChangeSetPersister; - try { +// Object around(EntityManager em, Object entity) : entityManagerRemove(em, entity) { +// if (entity instanceof DocumentBacked) { +// removeChangeSetValues((DocumentBacked)entity); +// } +// return proceed(em, entity); +// } + + private static void removeChangeSetValues(DocumentBacked entity) { + LOGGER.debug("Removing all change-set values for " + entity); + ChangeSet nulledCs = new HashMapChangeSet(); + DocumentBacked documentEntity = (DocumentBacked) entity; + @SuppressWarnings("unchecked") + ChangeSetPersister changeSetPersister = (ChangeSetPersister)documentEntity.itdChangeSetPersister; + try { changeSetPersister.getPersistentState( documentEntity.getClass(), documentEntity.get_persistent_id(), documentEntity.getChangeSet()); - } - catch (DataAccessException e) {} - catch (NotFoundException e) {} - for (String key : ((DocumentBacked)entity).getChangeSet().getValues().keySet()) { + } + catch (DataAccessException e) {} + catch (NotFoundException e) {} + for (String key :entity.getChangeSet().getValues().keySet()) { nulledCs.set(key, null); - } - ((DocumentBacked)entity).setChangeSet(nulledCs); - } - return proceed(em, entity); + } + entity.setChangeSet(nulledCs); } before(DocumentBacked entity) : arbitraryUserConstructorOfChangeSetBackedObject(entity) { @@ -204,6 +209,7 @@ public aspect MongoDocumentBacking { LOGGER.debug("JPA lifecycle event PostRemove: " + this.getClass().getName() + " :: " + this); } registerTransactionSynchronization(this); + removeChangeSetValues(this); } @javax.persistence.PostLoad public void DocumentBacked.itdPostLoad() { if (LOGGER.isDebugEnabled()) {