You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2008/12/07 17:20:38 UTC

svn commit: r724150 - in /cayenne/main/tags/3.0M5/cayenne: docs/doc/src/main/resources/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/ framework...

Author: aadamchik
Date: Sun Dec  7 08:20:38 2008
New Revision: 724150

URL: http://svn.apache.org/viewvc?rev=724150&view=rev
Log:
CAY-1138 Stop using Query.isRefreshingObjects()

undoing removal of refresh logic as this breaks relationship query

Added:
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextRelationshipQueryTest.java
Modified:
    cayenne/main/tags/3.0M5/cayenne/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataRowStore.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectResolver.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectStore.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectTreeResolver.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryMetadata.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/art/Artist.java
    cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextObjectIdQueryTest.java

Modified: cayenne/main/tags/3.0M5/cayenne/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/tags/3.0M5/cayenne/docs/doc/src/main/resources/RELEASE-NOTES.txt Sun Dec  7 08:20:38 2008
@@ -47,7 +47,7 @@
 CAY-1132 DataMap class generator mechanism for the ROP client
 CAY-1133  Split Maven cayenne:modeler goal into a separate plugin from cgen and others
 CAY-1137 Deprecate and start ignoring QueryMetadata.isResolvingInherited()
-CAY-1138 Stop using "QueryMetadata.isRefreshingObjects()"
+CAY-1138 Stop using Query.isRefreshingObjects()
 
 Bug fixes since M4:
 

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java Sun Dec  7 08:20:38 2008
@@ -618,7 +618,7 @@
     public List objectsFromDataRows(
             ClassDescriptor descriptor,
             List<? extends DataRow> dataRows) {
-        return new ObjectResolver(this, descriptor)
+        return new ObjectResolver(this, descriptor, true)
                 .synchronizedObjectsFromDataRows(dataRows);
     }
 

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java Sun Dec  7 08:20:38 2008
@@ -587,7 +587,8 @@
 
             // take a shortcut when no prefetches exist...
             if (prefetchTree == null) {
-                objects = new ObjectResolver(context, descriptor)
+                objects = new ObjectResolver(context, descriptor, metadata
+                        .isRefreshingObjects())
                         .synchronizedObjectsFromDataRows(normalizedRows);
             }
             else {

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataRowStore.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataRowStore.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataRowStore.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataRowStore.java Sun Dec  7 08:20:38 2008
@@ -192,8 +192,7 @@
                 EventBridgeFactory factory = (EventBridgeFactory) Class.forName(
                         eventBridgeFactory).newInstance();
 
-                Collection<EventSubject> subjects = Collections
-                        .singleton(getSnapshotEventSubject());
+                Collection<EventSubject> subjects = Collections.singleton(getSnapshotEventSubject());
                 String externalSubject = EventBridge
                         .convertToExternalSubject(getSnapshotEventSubject());
                 this.remoteNotificationsHandler = factory.createEventBridge(
@@ -212,9 +211,9 @@
     /**
      * Updates cached snapshots for the list of objects.
      * 
-     * @since 3.0
+     * @since 1.2
      */
-    void snapshotsUpdatedForObjects(List objects, List snapshots) {
+    void snapshotsUpdatedForObjects(List objects, List snapshots, boolean refresh) {
 
         int size = objects.size();
 
@@ -246,27 +245,30 @@
                 // missing
 
                 DataRow cachedSnapshot = (DataRow) this.snapshots.get(oid);
-                DataRow newSnapshot = (DataRow) snapshots.get(i);
+                if (refresh || cachedSnapshot == null) {
 
-                if (cachedSnapshot != null) {
-                    // use old snapshot if no changes occurred
-                    if (object instanceof DataObject
-                            && cachedSnapshot.equals(newSnapshot)) {
-                        ((DataObject) object).setSnapshotVersion(cachedSnapshot
-                                .getVersion());
-                        continue;
+                    DataRow newSnapshot = (DataRow) snapshots.get(i);
+
+                    if (cachedSnapshot != null) {
+                        // use old snapshot if no changes occurred
+                        if (object instanceof DataObject
+                                && cachedSnapshot.equals(newSnapshot)) {
+                            ((DataObject) object).setSnapshotVersion(cachedSnapshot
+                                    .getVersion());
+                            continue;
+                        }
+                        else {
+                            newSnapshot.setReplacesVersion(cachedSnapshot.getVersion());
+                        }
                     }
-                    else {
-                        newSnapshot.setReplacesVersion(cachedSnapshot.getVersion());
+
+                    if (modified == null) {
+                        modified = new HashMap();
+                        eventPostedBy = object.getObjectContext().getGraphManager();
                     }
-                }
 
-                if (modified == null) {
-                    modified = new HashMap();
-                    eventPostedBy = object.getObjectContext().getGraphManager();
+                    modified.put(oid, newSnapshot);
                 }
-
-                modified.put(oid, newSnapshot);
             }
 
             if (modified != null) {

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectResolver.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectResolver.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectResolver.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectResolver.java Sun Dec  7 08:20:38 2008
@@ -50,13 +50,14 @@
     Collection<DbAttribute> primaryKey;
 
     EntityInheritanceTree inheritanceTree;
+    boolean refreshObjects;
     DataRowStore cache;
 
-    ObjectResolver(DataContext context, ClassDescriptor descriptor) {
-        init(context, descriptor);
+    ObjectResolver(DataContext context, ClassDescriptor descriptor, boolean refresh) {
+        init(context, descriptor, refresh);
     }
 
-    void init(DataContext context, ClassDescriptor descriptor) {
+    void init(DataContext context, ClassDescriptor descriptor, boolean refresh) {
         // sanity check
         DbEntity dbEntity = descriptor.getEntity().getDbEntity();
         if (dbEntity == null) {
@@ -76,6 +77,7 @@
 
         this.context = context;
         this.cache = context.getObjectStore().getDataRowCache();
+        this.refreshObjects = refresh;
         this.descriptor = descriptor;
         this.inheritanceTree = context.getEntityResolver().lookupInheritanceTree(
                 descriptor.getEntity());
@@ -117,7 +119,7 @@
         }
 
         // now deal with snapshots
-        cache.snapshotsUpdatedForObjects(results, rows);
+        cache.snapshotsUpdatedForObjects(results, rows, refreshObjects);
 
         return results;
     }
@@ -182,7 +184,7 @@
         }
 
         // now deal with snapshots
-        cache.snapshotsUpdatedForObjects(results, rows);
+        cache.snapshotsUpdatedForObjects(results, rows, refreshObjects);
 
         return results;
     }
@@ -226,19 +228,26 @@
             case PersistenceState.COMMITTED:
             case PersistenceState.MODIFIED:
             case PersistenceState.DELETED:
-
-                DataRowUtils.mergeObjectWithSnapshot(
-                        context,
-                        classDescriptor,
-                        object,
-                        row);
-
-                if (object instanceof DataObject) {
-                    ((DataObject) object).setSnapshotVersion(row.getVersion());
+                // process the above only if refresh is requested...
+                if (refreshObjects) {
+                    DataRowUtils.mergeObjectWithSnapshot(
+                            context,
+                            classDescriptor,
+                            object,
+                            row);
+
+                    if (object instanceof DataObject) {
+                        ((DataObject) object).setSnapshotVersion(row.getVersion());
+                    }
                 }
-
                 break;
             case PersistenceState.HOLLOW:
+                if (!refreshObjects) {
+                    DataRow cachedRow = cache.getCachedSnapshot(anId);
+                    if (cachedRow != null) {
+                        row = cachedRow;
+                    }
+                }
                 DataRowUtils.mergeObjectWithSnapshot(
                         context,
                         classDescriptor,

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectStore.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectStore.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectStore.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectStore.java Sun Dec  7 08:20:38 2008
@@ -424,7 +424,7 @@
         DataRowStore cache = getDataRowCache();
         if (cache != null) {
             synchronized (this) {
-                cache.snapshotsUpdatedForObjects(objects, snapshots);
+                cache.snapshotsUpdatedForObjects(objects, snapshots, refresh);
             }
         }
     }

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectTreeResolver.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectTreeResolver.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectTreeResolver.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ObjectTreeResolver.java Sun Dec  7 08:20:38 2008
@@ -217,7 +217,8 @@
             }
 
             node.setDataRows(rows);
-            node.setResolver(new ObjectResolver(context, descriptor));
+            node.setResolver(new ObjectResolver(context, descriptor, queryMetadata
+                    .isRefreshingObjects()));
             node.setIncoming(arc);
 
             if (currentNode != null) {
@@ -274,7 +275,8 @@
 
                 cache.snapshotsUpdatedForObjects(
                         objects,
-                        ((PrefetchProcessorJointNode) processorNode).getResolvedRows());
+                        ((PrefetchProcessorJointNode) processorNode).getResolvedRows(),
+                        queryMetadata.isRefreshingObjects());
             }
             // disjoint prefetch on flattened relationships still requires manual matching
             else if (processorNode.getIncoming() != null
@@ -477,7 +479,8 @@
             if (!processorNode.getObjects().isEmpty()) {
                 cache.snapshotsUpdatedForObjects(
                         processorNode.getObjects(),
-                        processorNode.getResolvedRows());
+                        processorNode.getResolvedRows(),
+                        queryMetadata.isRefreshingObjects());
             }
 
             // run 'connectToParents' even if the object list is empty. This is needed to

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/DefaultQueryMetadata.java Sun Dec  7 08:20:38 2008
@@ -113,9 +113,6 @@
         return QueryMetadata.FETCHING_DATA_ROWS_DEFAULT;
     }
 
-    /**
-     * @deprecated since 3.0
-     */
     public boolean isRefreshingObjects() {
         return true;
     }

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryMetadata.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryMetadata.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryMetadata.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/QueryMetadata.java Sun Dec  7 08:20:38 2008
@@ -221,10 +221,6 @@
      * Returns <code>true</code> if the query results should replace any currently cached
      * values, returns <code>false</code> otherwise. If {@link #isFetchingDataRows()}
      * returns <code>true</code>, this setting is not applicable and has no effect.
-     * 
-     * @deprecated since 3.0. With introduction of the cache strategies this setting is
-     *             redundant, although it is still being taken into account. It will be
-     *             removed in the later versions of Cayenne.
      */
     boolean isRefreshingObjects();
 

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/art/Artist.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/art/Artist.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/art/Artist.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/art/Artist.java Sun Dec  7 08:20:38 2008
@@ -33,6 +33,7 @@
     protected boolean postRemoved;
     protected boolean postPersisted;
     protected int postLoaded;
+    protected transient int propertyWrittenDirectly;
 
     protected String someOtherProperty;
     protected Object someOtherObjectProperty;
@@ -139,4 +140,15 @@
     public void setSomeOtherObjectProperty(Object object) {
         someOtherObjectProperty = object;
     }
+    
+    @Override
+    public void writePropertyDirectly(String propName, Object val) {
+        propertyWrittenDirectly++;
+        super.writePropertyDirectly(propName, val);
+    }
+    
+    public int getPropertyWrittenDirectly() {
+        return propertyWrittenDirectly;
+    }
+
 }

Modified: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextObjectIdQueryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextObjectIdQueryTest.java?rev=724150&r1=724149&r2=724150&view=diff
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextObjectIdQueryTest.java (original)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextObjectIdQueryTest.java Sun Dec  7 08:20:38 2008
@@ -61,6 +61,30 @@
         assertNull(a1.getDateOfBirth());
         assertEquals("X", a1.getArtistName());
     }
+    
+    public void testNoRefreshValuesNew() {
+
+        DataContext context = createDataContext();
+
+        Artist a = context.newObject(Artist.class);
+        a.setArtistName("X");
+
+        context.commitChanges();
+
+        context.performGenericQuery(new SQLTemplate(
+                Artist.class,
+                "UPDATE ARTIST SET ARTIST_NAME = 'Y'"));
+
+        long id = DataObjectUtils.longPKForObject(a);
+        ObjectIdQuery query = new ObjectIdQuery(new ObjectId(
+                "Artist",
+                Artist.ARTIST_ID_PK_COLUMN,
+                id), false, ObjectIdQuery.CACHE);
+
+        Artist a1 = (Artist) DataObjectUtils.objectForQuery(context, query);
+        assertEquals("X", a1.getArtistName());
+    }
+    
 
     public void testRefreshNullifiedValuesExisting() {
 

Added: cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextRelationshipQueryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextRelationshipQueryTest.java?rev=724150&view=auto
==============================================================================
--- cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextRelationshipQueryTest.java (added)
+++ cayenne/main/tags/3.0M5/cayenne/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextRelationshipQueryTest.java Sun Dec  7 08:20:38 2008
@@ -0,0 +1,129 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.cayenne.access;
+
+import java.util.List;
+
+import org.apache.art.Artist;
+import org.apache.art.Painting;
+import org.apache.cayenne.DataObjectUtils;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.query.QueryChain;
+import org.apache.cayenne.query.RelationshipQuery;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.unit.CayenneCase;
+
+public class DataContextRelationshipQueryTest extends CayenneCase {
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        deleteTestData();
+    }
+
+    public void testUnrefreshingToOne() {
+
+        ObjectContext context = createDataContext();
+
+        QueryChain chain = new QueryChain();
+        chain.addQuery(new SQLTemplate(
+                Artist.class,
+                "INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (1, 'a1')"));
+        chain
+                .addQuery(new SQLTemplate(
+                        Painting.class,
+                        "INSERT INTO PAINTING (PAINTING_ID, ARTIST_ID, PAINTING_TITLE) VALUES (1, 1, 'p1')"));
+
+        context.performQuery(chain);
+
+        Painting p = DataObjectUtils.objectForPK(context, Painting.class, 1);
+
+        // resolve artist once before running non-refreshing query, to check that we do
+        // not refresh the object
+
+        Artist a = DataObjectUtils.objectForPK(context, Artist.class, 1);
+        long v = a.getSnapshotVersion();
+        int writeCalls = a.getPropertyWrittenDirectly();
+        assertEquals("a1", a.getArtistName());
+
+        context.performQuery(new SQLTemplate(
+                Artist.class,
+                "UPDATE ARTIST SET ARTIST_NAME = 'a2' WHERE ARTIST_ID = 1"));
+
+        RelationshipQuery toOne = new RelationshipQuery(
+                p.getObjectId(),
+                Painting.TO_ARTIST_PROPERTY,
+                false);
+
+        List<Artist> related = context.performQuery(toOne);
+        assertEquals(1, related.size());
+        assertTrue(related.contains(a));
+        assertEquals("a1", a.getArtistName());
+        assertEquals(v, a.getSnapshotVersion());
+        assertEquals(
+                "Looks like relationship query caused snapshot refresh",
+                writeCalls,
+                a.getPropertyWrittenDirectly());
+    }
+
+    public void testRefreshingToOne() {
+
+        ObjectContext context = createDataContext();
+
+        QueryChain chain = new QueryChain();
+        chain.addQuery(new SQLTemplate(
+                Artist.class,
+                "INSERT INTO ARTIST (ARTIST_ID, ARTIST_NAME) VALUES (1, 'a1')"));
+        chain
+                .addQuery(new SQLTemplate(
+                        Painting.class,
+                        "INSERT INTO PAINTING (PAINTING_ID, ARTIST_ID, PAINTING_TITLE) VALUES (1, 1, 'p1')"));
+
+        context.performQuery(chain);
+
+        Painting p = DataObjectUtils.objectForPK(context, Painting.class, 1);
+
+        // resolve artist once before running non-refreshing query, to check that we do
+        // not refresh the object
+
+        Artist a = DataObjectUtils.objectForPK(context, Artist.class, 1);
+        long v = a.getSnapshotVersion();
+        int writeCalls = a.getPropertyWrittenDirectly();
+        assertEquals("a1", a.getArtistName());
+
+        context.performQuery(new SQLTemplate(
+                Artist.class,
+                "UPDATE ARTIST SET ARTIST_NAME = 'a2' WHERE ARTIST_ID = 1"));
+
+        RelationshipQuery toOne = new RelationshipQuery(
+                p.getObjectId(),
+                Painting.TO_ARTIST_PROPERTY,
+                true);
+
+        List<Artist> related = context.performQuery(toOne);
+        assertEquals(1, related.size());
+        assertTrue(related.contains(a));
+        assertEquals("a2", a.getArtistName());
+        assertTrue("Looks like relationship query didn't cause a snapshot refresh", v < a
+                .getSnapshotVersion());
+        assertTrue(
+                "Looks like relationship query didn't cause a snapshot refresh",
+                writeCalls < a.getPropertyWrittenDirectly());
+    }
+}