I found a workaround. When I modify the collection, before persisting
the changes, I explicitly call JDOHelper.makeDirty() to tell JDO the
collection has changed. I've tested this with the test code below and
it works:
public void setTestString(String testString)
{
if (testStrings == null)
{
testStrings = new ArrayList<String>();
}
this.testString = testString;
this.testStrings.add(testString);
JDOHelper.makeDirty(this, "testStrings"); //
<========= added this line.
}
On Sep 6, 4:00 pm, Jeff <[email protected]> wrote:
> Am I doing these JDO operations wrong or is there a bug/limitation in
> the appengine JDO implementation?
>
> Using JDO, I can persist new entities in the datastore that contain a
> serialized collection and read them back. But when I attempt to
> update an existing entity, it persists the changes to all properties
> except the serialized collection. Is there some way I'm supposed to
> indicate that the serialized collection has changed and therefore
> needs to be persisted?
>
> Here is some test code that demonstrates the problem. Relevant output
> follows the code.
>
> @PersistenceCapable(identityType = IdentityType.APPLICATION)
> public class SerialTest2
> {
> @SuppressWarnings("unused")
> @PrimaryKey
> @Persistent
> private String key;
> @Persistent
> private String testString;
> @Serialized
> ArrayList<String> testStrings;
>
> public SerialTest2()
> {
> }
>
> public void setKey(String key)
> {
> this.key = key;
> }
> public void setTestString(String testString)
> {
> if (testStrings == null)
> {
> testStrings = new ArrayList<String>();
> }
> this.testString = testString;
> this.testStrings.add(testString);
> }
>
> public String getTestString()
> {
> return this.testString;
> }
>
> public ArrayList<String> getTestStrings()
> {
> return this.testStrings;
> }
>
> }
>
> log.info("Insert/Update
> ------------------------------------");
> List<SerialTest2> st2List = null;
> PersistenceManager pm = PMF.get().getPersistenceManager();
> pm.currentTransaction().begin();
> try
> {
> StringBuilder sb = new StringBuilder();
> sb.append("select from ");
> sb.append(SerialTest2.class.getName());
> sb.append(" where key == 'A123'");
> st2List = (List<SerialTest2>) pm.newQuery(sb.toString
> ()).execute();
> if (st2List == null || st2List.size() < 1)
> {
> log.info("No existing record found");
> SerialTest2 st2 = new SerialTest2();
> st2.setKey("A123");
> st2.setTestString("First Test String");
> pm.makePersistent(st2);
> }
> else
> {
> log.info("Found existing record");
> log.info("--testString: " + st2List.get
> (0).getTestString());
> ArrayList<String> testStrings = st2List.get
> (0).getTestStrings();
> for (String s: testStrings)
> {
> log.info("--testStrings: " + s);
> }
> st2List.get(0).setTestString("Second Test String");
>
> log.info("Updated record ready to persist");
> log.info("--testString: " + st2List.get
> (0).getTestString());
> testStrings = st2List.get(0).getTestStrings();
> for (String s: testStrings)
> {
> log.info("--testStrings: " + s);
> }
>
> pm.makePersistentAll(st2List);
> }
> pm.currentTransaction().commit();
> }
> catch (javax.jdo.JDOObjectNotFoundException e)
> {
> log.info("Threw JDOObjectNotFoundException");
> }
> catch (Exception e)
> {
> StringWriter sw = new StringWriter();
> e.printStackTrace(new PrintWriter(sw));
> log.severe("Error during insert/update step: " +
> sw.toString());
> }
> finally
> {
> if (pm.currentTransaction().isActive())
> {
> pm.currentTransaction().rollback();
> }
> pm.close();
> }
>
> log.info("Query
> --------------------------------------------");
>
> pm = PMF.get().getPersistenceManager();
> try
> {
> StringBuilder sb = new StringBuilder();
> sb.append("select from ");
> sb.append(SerialTest2.class.getName());
> sb.append(" where key == 'A123'");
> st2List = (List<SerialTest2>) pm.newQuery(sb.toString
> ()).execute();
> if (st2List == null || st2List.size() < 1)
> {
> log.info("No existing record found");
> }
> else
> {
> log.info("Found existing record");
> log.info("--testString: " + st2List.get
> (0).getTestString());
> ArrayList<String> testStrings = st2List.get
> (0).getTestStrings();
> for (String s: testStrings)
> {
> log.info("--testStrings: " + s);
> }
> }
> }
> catch (javax.jdo.JDOObjectNotFoundException e)
> {
> log.info("Threw JDOObjectNotFoundException");
> }
> catch (Exception e)
> {
> StringWriter sw = new StringWriter();
> e.printStackTrace(new PrintWriter(sw));
> log.severe("Error during query step: " + sw.toString());
> }
> finally
> {
> pm.close();
> }
>
> First run (when it creates a new datastore entity):
>
> INFO: Insert/Update ------------------------------------
> INFO: No existing record found
> INFO: Query --------------------------------------------
> INFO: Found existing record
> INFO: --testString: First Test String
> INFO: --testStrings: First Test String
>
> Second run (when it updates the entity):
>
> INFO: Insert/Update ------------------------------------
> INFO: Found existing record
> INFO: --testString: First Test String
> INFO: --testStrings: First Test String
> INFO: Updated record ready to persist
> INFO: --testString: Second Test String
> INFO: --testStrings: First Test String
> INFO: --testStrings: Second Test String
> INFO: Query --------------------------------------------
> INFO: Found existing record
> INFO: --testString: Second Test String
> INFO: --testStrings: First Test String
>
> Note that the query returned an entity with "testString" updated, but
> "testStrings" still contains only one item--in other words it was not
> updated.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Google App Engine" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/google-appengine?hl=en
-~----------~----~----~----~------~----~------~--~---