This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
View | Details | Raw Unified | Return to bug 298985 | Differences between
and this patch

Collapse All | Expand All

(-)dbws/org.eclipse.persistence.dbws/src/org/eclipse/persistence/internal/xr/XRDynamicEntity.java (-21 / +4 lines)
Lines 14-23 Link Here
14
14
15
//javase imports
15
//javase imports
16
import java.beans.PropertyChangeListener;
16
import java.beans.PropertyChangeListener;
17
import java.util.Vector;
18
17
19
//java extension imports
20
21
//EclipseLink imports
18
//EclipseLink imports
22
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
19
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
23
import org.eclipse.persistence.dynamic.DynamicEntity;
20
import org.eclipse.persistence.dynamic.DynamicEntity;
Lines 112-130 Link Here
112
    }
109
    }
113
110
114
    //PersistenceEntity API
111
    //PersistenceEntity API
115
    protected CacheKey __cacheKey;
112
    protected Object __pk;
116
    protected Vector __pk;
113
    public Object _persistence_getId() {
117
    // perf. optimization - cache the __cacheKey and pkVector
118
    public CacheKey _persistence_getCacheKey() {
119
        return __cacheKey;
120
    }
121
    public void _persistence_setCacheKey(CacheKey cacheKey) {
122
        this.__cacheKey = cacheKey;
123
    }
124
    public Vector _persistence_getPKVector() {
125
        return __pk;
114
        return __pk;
126
    }
115
    }
127
    public void _persistence_setPKVector(Vector pk) {
116
    public void _persistence_setId(Object pk) {
128
        this.__pk = pk;
117
        this.__pk = pk;
129
    }
118
    }
130
    
119
    
Lines 195-207 Link Here
195
        // this will print something like {Emp 10} or {Phone 234-5678 10}
184
        // this will print something like {Emp 10} or {Phone 234-5678 10}
196
        StringBuilder sb = new StringBuilder(20);
185
        StringBuilder sb = new StringBuilder(20);
197
        sb.append('{');
186
        sb.append('{');
198
        sb.append(getShortClassName(this.getClass()));
187
        sb.append(__pk);
199
        if (__pk != null) {
200
            for (int i = 0; i < __pk.size(); i++) {
201
                sb.append(' ');
202
                sb.append(__pk.elementAt(i));
203
            }
204
        }
205
        sb.append('}');
188
        sb.append('}');
206
        return sb.toString();
189
        return sb.toString();
207
    }
190
    }
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/framework/JoinedAttributeTestHelper.java (-5 lines)
Lines 223-229 Link Here
223
            HashMap map1 = new HashMap(col1.size());
223
            HashMap map1 = new HashMap(col1.size());
224
            HashMap map2 = new HashMap(col2.size());
224
            HashMap map2 = new HashMap(col2.size());
225
            
225
            
226
            boolean simplePk = desc.getPrimaryKeyFields().size()==1;
227
            ObjectBuilder builder = desc.getObjectBuilder();
226
            ObjectBuilder builder = desc.getObjectBuilder();
228
            Iterator it1 = col1.iterator();
227
            Iterator it1 = col1.iterator();
229
            Iterator it2 = col2.iterator();
228
            Iterator it2 = col2.iterator();
Lines 232-241 Link Here
232
                Object obj2 = it2.next();
231
                Object obj2 = it2.next();
233
                Object pk1 = builder.extractPrimaryKeyFromObject(obj1, session);
232
                Object pk1 = builder.extractPrimaryKeyFromObject(obj1, session);
234
                Object pk2 = builder.extractPrimaryKeyFromObject(obj2, session);
233
                Object pk2 = builder.extractPrimaryKeyFromObject(obj2, session);
235
                if(simplePk) {
236
                    pk1 = ((Vector)pk1).firstElement();
237
                    pk2 = ((Vector)pk2).firstElement();
238
                }
239
                map1.put(pk1, obj1);
234
                map1.put(pk1, obj1);
240
                map2.put(pk2, obj2);
235
                map2.put(pk2, obj2);
241
            }
236
            }
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/interfaces/PostCommitEventPrimaryKeyTest.java (-2 / +2 lines)
Lines 50-58 Link Here
50
        UnitOfWorkChangeSet uowChangeSet = uow.getUnitOfWorkChangeSet();
50
        UnitOfWorkChangeSet uowChangeSet = uow.getUnitOfWorkChangeSet();
51
        for (Iterator changes = uowChangeSet.getAllChangeSets().keySet().iterator(); changes.hasNext(); ) {
51
        for (Iterator changes = uowChangeSet.getAllChangeSets().keySet().iterator(); changes.hasNext(); ) {
52
            ObjectChangeSet objChangeSet = (ObjectChangeSet)changes.next();
52
            ObjectChangeSet objChangeSet = (ObjectChangeSet)changes.next();
53
            Vector objKey = objChangeSet.getPrimaryKeys();
53
            Object objKey = objChangeSet.getId();
54
54
55
            if (objKey == null || objKey.isEmpty()) {
55
            if (objKey == null) {
56
                emptyKey = true;
56
                emptyKey = true;
57
            }
57
            }
58
        }
58
        }
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/optimisticlocking/ChangeSetOptimisticLockingUpdateTest.java (-1 / +1 lines)
Lines 54-60 Link Here
54
        ObjectChangeSet changeSet = (ObjectChangeSet)uow.getUnitOfWorkChangeSet().getObjectChangeSetForClone(originalObject);
54
        ObjectChangeSet changeSet = (ObjectChangeSet)uow.getUnitOfWorkChangeSet().getObjectChangeSetForClone(originalObject);
55
        Object lockValue = 
55
        Object lockValue = 
56
            getSession().getDescriptor(domainClass).getOptimisticLockingPolicy().getWriteLockValue(originalObject, 
56
            getSession().getDescriptor(domainClass).getOptimisticLockingPolicy().getWriteLockValue(originalObject, 
57
                                                                                                   changeSet.getPrimaryKeys(), 
57
                                                                                                   changeSet.getId(), 
58
                                                                                                   (AbstractSession)getSession());
58
                                                                                                   (AbstractSession)getSession());
59
        if (lockValue instanceof Number){
59
        if (lockValue instanceof Number){
60
            if (((Number)changeSet.getWriteLockValue()).longValue() !=((Number)lockValue).longValue()) {
60
            if (((Number)changeSet.getWriteLockValue()).longValue() !=((Number)lockValue).longValue()) {
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/performance/emulateddb/EmulatedDriver.java (-1 / +1 lines)
Lines 59-65 Link Here
59
            return null;
59
            return null;
60
        }
60
        }
61
        if (connection == null) {
61
        if (connection == null) {
62
            connection = new EmulatedConnection(DriverManager.getConnection(url.substring("emulate:".length() + 1, url.length()), info));
62
            connection = new EmulatedConnection(DriverManager.getConnection(url.substring("emulate:".length(), url.length()), info));
63
        }
63
        }
64
        return connection;
64
        return connection;
65
    }
65
    }
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/queries/EmployeeWrapperPolicy.java (-4 / +2 lines)
Lines 12-18 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.testing.tests.queries;
13
package org.eclipse.persistence.testing.tests.queries;
14
14
15
import java.util.*;
16
import org.eclipse.persistence.descriptors.*;
15
import org.eclipse.persistence.descriptors.*;
17
import org.eclipse.persistence.testing.models.employee.domain.*;
16
import org.eclipse.persistence.testing.models.employee.domain.*;
18
import org.eclipse.persistence.exceptions.*;
17
import org.eclipse.persistence.exceptions.*;
Lines 84-92 Link Here
84
    public Object unwrapObject(Object proxy, AbstractSession session) {
83
    public Object unwrapObject(Object proxy, AbstractSession session) {
85
        if (proxy instanceof WrappedEmployee) {
84
        if (proxy instanceof WrappedEmployee) {
86
            timesUnwrapCalled++;
85
            timesUnwrapCalled++;
87
            Vector primaryKey = new Vector(1);
86
            Object primaryKey = ((WrappedEmployee)proxy).getId();
88
            primaryKey.add(((WrappedEmployee)proxy).getId());
87
            return session.getIdentityMapAccessor().getFromIdentityMap(primaryKey, Employee.class);
89
            return session.getIdentityMapAccessor().getFromIdentityMap((Object)primaryKey, Employee.class);
90
        } else {
88
        } else {
91
            return proxy;
89
            return proxy;
92
        }
90
        }
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/queries/inmemory/UnitOfWorkConformNewObjectTest.java (-5 / +5 lines)
Lines 94-110 Link Here
94
        queryReadObject_1_ByObject.setReferenceClass(Employee.class);
94
        queryReadObject_1_ByObject.setReferenceClass(Employee.class);
95
        queryReadObject_1_ByObject.conformResultsInUnitOfWork();
95
        queryReadObject_1_ByObject.conformResultsInUnitOfWork();
96
        queryReadObject_1_ByObject.setSelectionObject(emp1);
96
        queryReadObject_1_ByObject.setSelectionObject(emp1);
97
        if(emp1 != uow.executeQuery(queryReadObject_1_ByObject)) {
97
        Employee result = (Employee)uow.executeQuery(queryReadObject_1_ByObject);
98
        if (emp1 != result) {
98
            errorMsg += "queryReadObject_1_ByObject: emp1; ";
99
            errorMsg += "queryReadObject_1_ByObject: emp1; ";
99
        }
100
        }
100
101
101
        ReadObjectQuery queryReadObject_1_ByKey = new ReadObjectQuery();
102
        ReadObjectQuery queryReadObject_1_ByKey = new ReadObjectQuery();
102
        queryReadObject_1_ByKey.setReferenceClass(Employee.class);
103
        queryReadObject_1_ByKey.setReferenceClass(Employee.class);
103
        queryReadObject_1_ByKey.conformResultsInUnitOfWork();
104
        queryReadObject_1_ByKey.conformResultsInUnitOfWork();
104
        Vector key = new Vector(1);
105
        queryReadObject_1_ByKey.setSelectionId(emp1.getId());
105
        key.add(emp1.getId());
106
        result = (Employee)uow.executeQuery(queryReadObject_1_ByKey);
106
        queryReadObject_1_ByKey.setSelectionId(key);
107
        if (emp1 != result) {
107
        if(emp1 != uow.executeQuery(queryReadObject_1_ByKey)) {
108
            errorMsg += "queryReadObject_1_ByKey: emp1; ";
108
            errorMsg += "queryReadObject_1_ByKey: emp1; ";
109
        }
109
        }
110
110
(-)foundation/eclipselink.core.test/src/org/eclipse/persistence/testing/tests/unidirectional/UnidirectionalEmployeeBasicTestModel.java (-16 / +9 lines)
Lines 14-20 Link Here
14
14
15
import java.util.ArrayList;
15
import java.util.ArrayList;
16
import java.util.List;
16
import java.util.List;
17
import java.util.Vector;
18
17
19
import org.eclipse.persistence.expressions.Expression;
18
import org.eclipse.persistence.expressions.Expression;
20
import org.eclipse.persistence.expressions.ExpressionBuilder;
19
import org.eclipse.persistence.expressions.ExpressionBuilder;
Lines 370-394 Link Here
370
            uow.registerObject(employee);
369
            uow.registerObject(employee);
371
            uow.commit();
370
            uow.commit();
372
            
371
            
373
            Vector pk = new Vector(1);
372
            version[0] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
374
            pk.add(manager.getId());
375
            
373
            
376
            version[0] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
377
            
378
            // test1 - add managed employee, manager's version should increment.
374
            // test1 - add managed employee, manager's version should increment.
379
            uow = getSession().acquireUnitOfWork();
375
            uow = getSession().acquireUnitOfWork();
380
            Employee managerClone = (Employee)uow.registerObject(manager);
376
            Employee managerClone = (Employee)uow.registerObject(manager);
381
            Employee employeeClone = (Employee)uow.registerObject(employee);
377
            Employee employeeClone = (Employee)uow.registerObject(employee);
382
            managerClone.addManagedEmployee(employeeClone);
378
            managerClone.addManagedEmployee(employeeClone);
383
            uow.commit();
379
            uow.commit();
384
            version[1] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
380
            version[1] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
385
            
381
            
386
            // test2 - alter managed employee, manager's version should NOT increment.
382
            // test2 - alter managed employee, manager's version should NOT increment.
387
            uow = getSession().acquireUnitOfWork();
383
            uow = getSession().acquireUnitOfWork();
388
            employeeClone = (Employee)uow.registerObject(employee);
384
            employeeClone = (Employee)uow.registerObject(employee);
389
            employeeClone.setFirstName("Altered");
385
            employeeClone.setFirstName("Altered");
390
            uow.commit();
386
            uow.commit();
391
            version[2] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
387
            version[2] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
392
            
388
            
393
            // test3- remove managed employee, manager's version should increment.
389
            // test3- remove managed employee, manager's version should increment.
394
            uow = getSession().acquireUnitOfWork();
390
            uow = getSession().acquireUnitOfWork();
Lines 396-402 Link Here
396
            employeeClone = (Employee)uow.registerObject(employee);
392
            employeeClone = (Employee)uow.registerObject(employee);
397
            managerClone.removeManagedEmployee(employeeClone);
393
            managerClone.removeManagedEmployee(employeeClone);
398
            uow.commit();
394
            uow.commit();
399
            version[3] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
395
            version[3] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
400
            
396
            
401
            PhoneNumber phone = new PhoneNumber("home", "613", "1111111");
397
            PhoneNumber phone = new PhoneNumber("home", "613", "1111111");
402
            
398
            
Lines 406-419 Link Here
406
            PhoneNumber phoneClone = (PhoneNumber)uow.registerObject(phone);
402
            PhoneNumber phoneClone = (PhoneNumber)uow.registerObject(phone);
407
            managerClone.addPhoneNumber(phoneClone);
403
            managerClone.addPhoneNumber(phoneClone);
408
            uow.commit();
404
            uow.commit();
409
            version[4] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
405
            version[4] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
410
            
406
            
411
            // test5- alter phone, manager's version should increment.
407
            // test5- alter phone, manager's version should increment.
412
            uow = getSession().acquireUnitOfWork();
408
            uow = getSession().acquireUnitOfWork();
413
            phoneClone = (PhoneNumber)uow.registerObject(phone);
409
            phoneClone = (PhoneNumber)uow.registerObject(phone);
414
            phoneClone.setType("work");
410
            phoneClone.setType("work");
415
            uow.commit();
411
            uow.commit();
416
            version[5] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
412
            version[5] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
417
            
413
            
418
            // test6- remove phone, manager's version should increment.
414
            // test6- remove phone, manager's version should increment.
419
            uow = getSession().acquireUnitOfWork();
415
            uow = getSession().acquireUnitOfWork();
Lines 421-427 Link Here
421
            phoneClone = (PhoneNumber)uow.registerObject(phone);
417
            phoneClone = (PhoneNumber)uow.registerObject(phone);
422
            managerClone.removePhoneNumber(phoneClone);
418
            managerClone.removePhoneNumber(phoneClone);
423
            uow.commit();
419
            uow.commit();
424
            version[6] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, pk, getAbstractSession())).longValue();
420
            version[6] = ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(manager, manager.getId(), getAbstractSession())).longValue();
425
        }
421
        }
426
        public void verify() {
422
        public void verify() {
427
            int numTestsFailed = 0;
423
            int numTestsFailed = 0;
Lines 587-597 Link Here
587
        public TargetLockingTest() {
583
        public TargetLockingTest() {
588
            super();
584
            super();
589
        }
585
        }
590
        long getVersion(Employee emp) {
586
        long getVersion(Employee emp) {            
591
            Vector pk = new Vector(1);
587
            return ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(emp, emp.getId(), getAbstractSession())).longValue();
592
            pk.add(emp.getId());
593
            
594
            return ((Long)getSession().getDescriptor(Employee.class).getOptimisticLockingPolicy().getWriteLockValue(emp, pk, getAbstractSession())).longValue();
595
        }
588
        }
596
        public void reset() {
589
        public void reset() {
597
            UnitOfWork uow = getSession().acquireUnitOfWork();
590
            UnitOfWork uow = getSession().acquireUnitOfWork();
(-)foundation/org.eclipse.persistence.core/resource/xsd/eclipselink_orm_2_0.xsd (-1 / +51 lines)
Lines 1943-1948 Link Here
1943
    </xsd:restriction>
1943
    </xsd:restriction>
1944
  </xsd:simpleType>
1944
  </xsd:simpleType>
1945
1945
1946
  <xsd:simpleType name="cache-key-type">
1947
    <xsd:annotation>
1948
      <xsd:documentation>
1949
            
1950
            /**
1951
             * Configures what type of Id value is used to store the object in the cache.
1952
             * This can either be the basic Id value for simple singleton Ids,
1953
             * or an optimized CacheKey type.
1954
             * 
1955
             * @see PrimaryKey#cacheKeyType()
1956
             * @see ClassDescriptor#setCacheKeyType(CacheKeyType)
1957
             * @author James Sutherland
1958
             * @since EclipseLink 2.1
1959
             */
1960
            public enum CacheKeyType {
1961
                /**
1962
                 * This can only be used for simple singleton Ids, such as long/int/String.
1963
                 * This is the default for simple singleton Ids.
1964
                 */
1965
                ID_VALUE,
1966
            
1967
                /**
1968
                 * Optimized cache key type that allows composite and complex values.
1969
                 * This is the default for composite or complex Ids.
1970
                 */
1971
                CACHE_KEY,
1972
            
1973
                /**
1974
                 * The cache key type is automatically configured depending on what is optimal for the class.
1975
                 */
1976
                AUTO
1977
            }
1978
1979
      </xsd:documentation>
1980
    </xsd:annotation>
1981
1982
    <xsd:restriction base="xsd:token">
1983
      <xsd:enumeration value="ID_VALUE"/>
1984
      <xsd:enumeration value="CACHE_KEY"/>
1985
      <xsd:enumeration value="AUTO"/>
1986
    </xsd:restriction>
1987
  </xsd:simpleType>
1988
  
1946
  <!-- **************************************************** -->
1989
  <!-- **************************************************** -->
1947
1990
1948
  <xsd:complexType name="inheritance">
1991
  <xsd:complexType name="inheritance">
Lines 3015-3020 Link Here
3015
          IdValidation validation() default IdValidation.ZERO; 
3058
          IdValidation validation() default IdValidation.ZERO; 
3016
3059
3017
          /**
3060
          /**
3061
           * (Optional) Configures what cache key type is used to store the object in the cache.
3062
           * By default the type is determined by what type is optimal for the class.
3063
           */
3064
          CacheKeyType cacheKeyType() default CacheKeyType.AUTO;
3065
    
3066
          /**
3018
           * (Optional) Used to specify the primary key columns directly.
3067
           * (Optional) Used to specify the primary key columns directly.
3019
           * This can be used instead of @Id if the primary key includes a non basic field,
3068
           * This can be used instead of @Id if the primary key includes a non basic field,
3020
           * such as a foreign key, or a inheritance discriminator, embedded, or transformation mapped field.
3069
           * such as a foreign key, or a inheritance discriminator, embedded, or transformation mapped field.
Lines 3025-3033 Link Here
3025
      </xsd:documentation>
3074
      </xsd:documentation>
3026
    </xsd:annotation>
3075
    </xsd:annotation>
3027
    <xsd:sequence>
3076
    <xsd:sequence>
3028
      <xsd:element name="column" type="orm:column" minOccurs="0" maxOccurs="unbounded"/>    
3077
      <xsd:element name="column" type="orm:column" minOccurs="0" maxOccurs="unbounded"/>
3029
    </xsd:sequence>
3078
    </xsd:sequence>
3030
    <xsd:attribute name="validation" type="orm:id-validation"/>
3079
    <xsd:attribute name="validation" type="orm:id-validation"/>
3080
    <xsd:attribute name="cache-key-type" type="orm:cache-key-type"/>
3031
  </xsd:complexType>
3081
  </xsd:complexType>
3032
3082
3033
  <!-- **************************************************** -->
3083
  <!-- **************************************************** -->
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/CacheKeyType.java (+44 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 1998, 2010 Oracle. All rights reserved.
3
 * This program and the accompanying materials are made available under the 
4
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
5
 * which accompanies this distribution. 
6
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
7
 * and the Eclipse Distribution License is available at 
8
 * http://www.eclipse.org/org/documents/edl-v10.php.
9
 *
10
 * Contributors:
11
 *     James Sutherland - allow for zero ids
12
 ******************************************************************************/
13
package org.eclipse.persistence.annotations;
14
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
16
17
/**
18
 * Configures what type of Id value is used to store the object in the cache.
19
 * This can either be the basic Id value for simple singleton Ids,
20
 * or an optimized CacheId type.
21
 * 
22
 * @see PrimaryKey#cacheKeyType()
23
 * @see ClassDescriptor#setCacheKeyType(CacheKeyType)
24
 * @author James Sutherland
25
 * @since EclipseLink 2.1
26
 */
27
public enum CacheKeyType {
28
    /**
29
     * This can only be used for simple singleton Ids, such as long/int/String.
30
     * This is the default for simple singleton Ids.
31
     */
32
    ID_VALUE,
33
34
    /**
35
     * Optimized cache key type that allows composite and complex values.
36
     * This is the default for composite or complex Ids.
37
     */
38
    CACHE_ID,
39
40
    /**
41
     * The cache key type is automatically configured depending on what is optimal for the class.
42
     */
43
    AUTO
44
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/annotations/PrimaryKey.java (-1 / +7 lines)
Lines 35-43 Link Here
35
     * (Optional) Configures what id validation is done.
35
     * (Optional) Configures what id validation is done.
36
     * By default 0 is not a valid id value, this can be used to allow 0 id values.
36
     * By default 0 is not a valid id value, this can be used to allow 0 id values.
37
     */
37
     */
38
    IdValidation validation() default IdValidation.ZERO; 
38
    IdValidation validation() default IdValidation.ZERO;
39
39
40
    /**
40
    /**
41
     * (Optional) Configures what cache key type is used to store the object in the cache.
42
     * By default the type is determined by what type is optimal for the class.
43
     */
44
    CacheKeyType cacheKeyType() default CacheKeyType.AUTO;
45
46
    /**
41
     * (Optional) Used to specify the primary key columns directly.
47
     * (Optional) Used to specify the primary key columns directly.
42
     * This can be used instead of @Id if the primary key includes a non basic field,
48
     * This can be used instead of @Id if the primary key includes a non basic field,
43
     * such as a foreign key, or a inheritance discriminator, embedded, or transformation mapped field.
49
     * such as a foreign key, or a inheritance discriminator, embedded, or transformation mapped field.
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/changetracking/AttributeChangeTrackingPolicy.java (-1 / +1 lines)
Lines 87-93 Link Here
87
        }
87
        }
88
88
89
        // The following code deals with reads that force changes to the flag associated with optimistic locking.
89
        // The following code deals with reads that force changes to the flag associated with optimistic locking.
90
        if ((descriptor.usesOptimisticLocking()) && (changes.getPrimaryKeys() != null)) {
90
        if ((descriptor.usesOptimisticLocking()) && (changes.getId() != null)) {
91
            changes.setOptimisticLockingPolicyAndInitialWriteLockValue(descriptor.getOptimisticLockingPolicy(), session);
91
            changes.setOptimisticLockingPolicyAndInitialWriteLockValue(descriptor.getOptimisticLockingPolicy(), session);
92
        }
92
        }
93
        
93
        
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/changetracking/DeferredChangeDetectionPolicy.java (-2 / +2 lines)
Lines 101-107 Link Here
101
            }
101
            }
102
        }
102
        }
103
        //Check if the user set the PK to null and throw an exception (bug# 4569755)
103
        //Check if the user set the PK to null and throw an exception (bug# 4569755)
104
        if (changes.getPrimaryKeys() == null && !isNew && !changes.isAggregate()) {
104
        if (changes.getId() == null && !isNew && !changes.isAggregate()) {
105
            if(!(unitOfWork.isNestedUnitOfWork()) || (unitOfWork.isNestedUnitOfWork() && !((UnitOfWorkImpl)unitOfWork.getParent()).isObjectNew(backUp))) {
105
            if(!(unitOfWork.isNestedUnitOfWork()) || (unitOfWork.isNestedUnitOfWork() && !((UnitOfWorkImpl)unitOfWork.getParent()).isObjectNew(backUp))) {
106
                throw ValidationException.nullPrimaryKeyInUnitOfWorkClone(clone);
106
                throw ValidationException.nullPrimaryKeyInUnitOfWorkClone(clone);
107
            }
107
            }
Lines 145-151 Link Here
145
        ObjectChangeSet changes = builder.createObjectChangeSet(clone, changeSet, isNew, true, session);
145
        ObjectChangeSet changes = builder.createObjectChangeSet(clone, changeSet, isNew, true, session);
146
146
147
        // The following code deals with reads that force changes to the flag associated with optimistic locking.
147
        // The following code deals with reads that force changes to the flag associated with optimistic locking.
148
        if ((descriptor.usesOptimisticLocking()) && (changes.getPrimaryKeys() != null)) {
148
        if ((descriptor.usesOptimisticLocking()) && (changes.getId() != null)) {
149
            changes.setOptimisticLockingPolicyAndInitialWriteLockValue(descriptor.getOptimisticLockingPolicy(), session);
149
            changes.setOptimisticLockingPolicyAndInitialWriteLockValue(descriptor.getOptimisticLockingPolicy(), session);
150
        }
150
        }
151
151
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/ClassDescriptor.java (-19 / +43 lines)
Lines 22-27 Link Here
22
import java.lang.reflect.*;
22
import java.lang.reflect.*;
23
23
24
import org.eclipse.persistence.internal.descriptors.*;
24
import org.eclipse.persistence.internal.descriptors.*;
25
import org.eclipse.persistence.internal.oxm.XMLObjectBuilder;
25
import org.eclipse.persistence.internal.sessions.AbstractRecord;
26
import org.eclipse.persistence.internal.sessions.AbstractRecord;
26
import org.eclipse.persistence.sequencing.Sequence;
27
import org.eclipse.persistence.sequencing.Sequence;
27
import org.eclipse.persistence.sessions.Project;
28
import org.eclipse.persistence.sessions.Project;
Lines 39-44 Link Here
39
import org.eclipse.persistence.internal.databaseaccess.*;
40
import org.eclipse.persistence.internal.databaseaccess.*;
40
import org.eclipse.persistence.exceptions.*;
41
import org.eclipse.persistence.exceptions.*;
41
import org.eclipse.persistence.sessions.remote.*;
42
import org.eclipse.persistence.sessions.remote.*;
43
import org.eclipse.persistence.annotations.CacheKeyType;
42
import org.eclipse.persistence.annotations.IdValidation;
44
import org.eclipse.persistence.annotations.IdValidation;
43
import org.eclipse.persistence.descriptors.copying.*;
45
import org.eclipse.persistence.descriptors.copying.*;
44
import org.eclipse.persistence.descriptors.changetracking.*;
46
import org.eclipse.persistence.descriptors.changetracking.*;
Lines 180-185 Link Here
180
    /** Allow zero primary key validation to be configured. */
182
    /** Allow zero primary key validation to be configured. */
181
    protected IdValidation idValidation;
183
    protected IdValidation idValidation;
182
    
184
    
185
    /** Allow cache key type to be configured. */
186
    protected CacheKeyType cacheKeyType;
187
    
183
    // JPA 2.0 Derived identities - map of mappings that act as derived ids
188
    // JPA 2.0 Derived identities - map of mappings that act as derived ids
184
    protected Map<String, DatabaseMapping> derivesIdMappings;
189
    protected Map<String, DatabaseMapping> derivesIdMappings;
185
    
190
    
Lines 844-853 Link Here
844
        if (!this.isAggregateDescriptor()) {
849
        if (!this.isAggregateDescriptor()) {
845
            session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregate(this.getJavaClass().getName(), mapping));
850
            session.getIntegrityChecker().handleError(DescriptorException.referenceDescriptorIsNotAggregate(this.getJavaClass().getName(), mapping));
846
        }
851
        }
847
        for (Enumeration stream = this.getInheritancePolicy().getChildDescriptors().elements();
852
        for (ClassDescriptor childDescriptor : this.getInheritancePolicy().getChildDescriptors()) {
848
                 stream.hasMoreElements();) {
849
            ClassDescriptor childDescriptor = (ClassDescriptor)stream.nextElement();
850
851
            // recurse down the inheritance tree to its leaves
853
            // recurse down the inheritance tree to its leaves
852
            childDescriptor.checkInheritanceTreeAggregateSettingsForChildren(session, mapping);
854
            childDescriptor.checkInheritanceTreeAggregateSettingsForChildren(session, mapping);
853
        }
855
        }
Lines 3183-3198 Link Here
3183
        // Make sure that child is post initialized,
3185
        // Make sure that child is post initialized,
3184
        // this initialize bottom up, unlike the two other phases that to top down.
3186
        // this initialize bottom up, unlike the two other phases that to top down.
3185
        if (hasInheritance()) {
3187
        if (hasInheritance()) {
3186
            for (Enumeration childEnum = getInheritancePolicy().getChildDescriptors().elements();
3188
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
3187
                     childEnum.hasMoreElements();) {
3189
                child.postInitialize(session);
3188
                ((ClassDescriptor)childEnum.nextElement()).postInitialize(session);
3189
            }
3190
            }
3190
        }
3191
        }
3191
3192
3192
        // Allow mapping to perform post initialization.
3193
        // Allow mapping to perform post initialization.
3193
        for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
3194
        for (DatabaseMapping mapping : getMappings()) {
3194
            DatabaseMapping mapping = (DatabaseMapping)mappingsEnum.nextElement();
3195
3196
            // This causes post init to be called multiple times in inheritance.
3195
            // This causes post init to be called multiple times in inheritance.
3197
            mapping.postInitialize(session);
3196
            mapping.postInitialize(session);
3198
            // PERF: computed if deferred locking is required.
3197
            // PERF: computed if deferred locking is required.
Lines 3235-3240 Link Here
3235
                }
3234
                }
3236
            }
3235
            }
3237
            field.setIndex(index);
3236
            field.setIndex(index);
3237
        }        
3238
        // Set cache key type.
3239
        if (getCacheKeyType() == null) {
3240
            if ((getPrimaryKeyFields().size() > 1) || (getObjectBuilder() instanceof XMLObjectBuilder)) {
3241
                setCacheKeyType(CacheKeyType.CACHE_ID);
3242
            } else if (getPrimaryKeyFields().size() == 1) {
3243
                Class type = getObjectBuilder().getFieldClassification(getPrimaryKeyFields().get(0));
3244
                if ((type == null) || type.isArray()) {
3245
                    setCacheKeyType(CacheKeyType.CACHE_ID);
3246
                } else {
3247
                    setCacheKeyType(CacheKeyType.ID_VALUE);
3248
                }
3249
            } else {
3250
                setCacheKeyType(CacheKeyType.CACHE_ID);                
3251
            }
3238
        }
3252
        }
3239
        getObjectBuilder().postInitialize(session);
3253
        getObjectBuilder().postInitialize(session);
3240
3254
Lines 3311-3319 Link Here
3311
        }
3325
        }
3312
        
3326
        
3313
        // Allow mapping pre init, must be done before validate.
3327
        // Allow mapping pre init, must be done before validate.
3314
        for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
3328
        for (DatabaseMapping mapping : getMappings()) {
3315
            try {
3329
            try {
3316
                DatabaseMapping mapping = (DatabaseMapping)mappingsEnum.nextElement();
3317
                mapping.preInitialize(session);
3330
                mapping.preInitialize(session);
3318
            } catch (DescriptorException exception) {
3331
            } catch (DescriptorException exception) {
3319
                session.getIntegrityChecker().handleError(exception);
3332
                session.getIntegrityChecker().handleError(exception);
Lines 3445-3457 Link Here
3445
        }
3458
        }
3446
        getObjectBuilder().initializeJoinedAttributes();
3459
        getObjectBuilder().initializeJoinedAttributes();
3447
        if (hasInheritance()) {
3460
        if (hasInheritance()) {
3448
			Vector children = getInheritancePolicy().getChildDescriptors(); 
3461
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
3449
			// use indices to avoid synchronization problems. 
3462
                child.reInitializeJoinedAttributes(); 
3450
            for (int i = 0; i < children.size(); i++) { 
3451
            	// Bug 6001198 - Child descriptors collection contains descriptors
3452
	            // also use 'i' indice, in order to correctly iterate
3453
    	        ClassDescriptor child = (ClassDescriptor)children.elementAt(i); 
3454
        	    child.reInitializeJoinedAttributes(); 
3455
            }
3463
            }
3456
        }
3464
        }
3457
    }
3465
    }
Lines 5427-5432 Link Here
5427
    }
5435
    }
5428
5436
5429
    /**
5437
    /**
5438
     * ADVANCED:
5439
     * Set what cache key type to use to store the object in the cache.
5440
     */
5441
    public void setCacheKeyType(CacheKeyType cacheKeyType) {
5442
        this.cacheKeyType = cacheKeyType;
5443
    }
5444
5445
    /**
5446
     * ADVANCED:
5447
     * Return what cache key type to use to store the object in the cache.
5448
     */
5449
    public CacheKeyType getCacheKeyType() {
5450
        return cacheKeyType;
5451
    }
5452
5453
    /**
5430
     * A Default Query Redirector will be applied to any executing object query
5454
     * A Default Query Redirector will be applied to any executing object query
5431
     * that does not have a more precise default (like the default
5455
     * that does not have a more precise default (like the default
5432
     * ReadObjectQuery Redirector) or a redirector set directly on the query.
5456
     * ReadObjectQuery Redirector) or a redirector set directly on the query.
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/CMPPolicy.java (-12 / +19 lines)
Lines 13-21 Link Here
13
package org.eclipse.persistence.descriptors;
13
package org.eclipse.persistence.descriptors;
14
14
15
import java.io.Serializable;
15
import java.io.Serializable;
16
import java.util.ArrayList;
17
import java.util.Arrays;
16
import java.util.HashSet;
18
import java.util.HashSet;
19
import java.util.List;
17
import java.util.Set;
20
import java.util.Set;
18
import java.util.Vector;
19
21
20
import org.eclipse.persistence.exceptions.DescriptorException;
22
import org.eclipse.persistence.exceptions.DescriptorException;
21
import org.eclipse.persistence.mappings.DatabaseMapping;
23
import org.eclipse.persistence.mappings.DatabaseMapping;
Lines 25-30 Link Here
25
import org.eclipse.persistence.queries.UpdateObjectQuery;
27
import org.eclipse.persistence.queries.UpdateObjectQuery;
26
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
28
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
27
import org.eclipse.persistence.internal.helper.DatabaseField;
29
import org.eclipse.persistence.internal.helper.DatabaseField;
30
import org.eclipse.persistence.internal.identitymaps.CacheId;
28
import org.eclipse.persistence.internal.sessions.AbstractSession;
31
import org.eclipse.persistence.internal.sessions.AbstractSession;
29
32
30
/**
33
/**
Lines 295-313 Link Here
295
    public Object createPrimaryKeyInstanceFromId(Object key, AbstractSession session) {
298
    public Object createPrimaryKeyInstanceFromId(Object key, AbstractSession session) {
296
        Object keyInstance = null;
299
        Object keyInstance = null;
297
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(getPKClass());
300
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(getPKClass());
298
        if (pkElementArray.length == 1 && pkElementArray[0] instanceof KeyIsElementAccessor) {
301
        List primaryKeyValues;
302
        if (key instanceof CacheId) {
303
            primaryKeyValues = new ArrayList(Arrays.asList(((CacheId)key).getPrimaryKey()));
304
        } else {
305
            primaryKeyValues = new ArrayList(1);
306
            primaryKeyValues.add(key);
307
        }
308
        if ((pkElementArray.length == 1) && (pkElementArray[0] instanceof KeyIsElementAccessor)) {
299
            DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[0].getAttributeName());
309
            DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(pkElementArray[0].getAttributeName());
300
            if (mapping.isDirectToFieldMapping()) {
310
            if (mapping.isDirectToFieldMapping()) {
301
                Converter converter = ((DirectToFieldMapping) mapping).getConverter();
311
                Converter converter = ((DirectToFieldMapping) mapping).getConverter();
302
                if (converter != null){
312
                if (converter != null){
303
                    return converter.convertDataValueToObjectValue(((Vector)key).get(0), session);
313
                    return converter.convertDataValueToObjectValue(primaryKeyValues.get(0), session);
304
                }
314
                }
305
                keyInstance = ((Vector)key).get(0);
315
                keyInstance = primaryKeyValues.get(0);
306
            } else if (mapping.isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the derived mapping.
316
            } else if (mapping.isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the derived mapping.
307
                //get reference descriptor and extract pk from target cmp policy
317
                //get reference descriptor and extract pk from target cmp policy
308
                keyInstance = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromId(key, session);
318
                keyInstance = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromId(key, session);
309
            }
319
            }
310
            ((Vector)key).remove(0); // remove processed key incase keys are complex and derrived
320
            primaryKeyValues.remove(0); // remove processed key incase keys are complex and derrived
311
        } else {
321
        } else {
312
            keyInstance = getPKClassInstance();
322
            keyInstance = getPKClassInstance();
313
            //get clone of Key so we can remove values.
323
            //get clone of Key so we can remove values.
Lines 316-327 Link Here
316
                DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(accessor.getAttributeName());
326
                DatabaseMapping mapping = getDescriptor().getObjectBuilder().getMappingForAttributeName(accessor.getAttributeName());
317
                Object fieldValue = null;
327
                Object fieldValue = null;
318
                if (mapping.isDirectToFieldMapping()) {
328
                if (mapping.isDirectToFieldMapping()) {
319
                    fieldValue = ((Vector)key).get(0);
329
                    fieldValue = primaryKeyValues.get(0);
320
                    Converter converter = ((DirectToFieldMapping) mapping).getConverter();
330
                    Converter converter = ((DirectToFieldMapping) mapping).getConverter();
321
                    if (converter != null){
331
                    if (converter != null){
322
                        fieldValue = converter.convertDataValueToObjectValue(fieldValue, session);
332
                        fieldValue = converter.convertDataValueToObjectValue(fieldValue, session);
323
                    }
333
                    }
324
                    ((Vector)key).remove(0);
334
                    primaryKeyValues.remove(0);
325
                } else if (mapping.isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the derived mapping.
335
                } else if (mapping.isObjectReferenceMapping()) { // what if mapping comes from derived ID.  need to get the derived mapping.
326
                    //get reference descriptor and extract pk from target cmp policy
336
                    //get reference descriptor and extract pk from target cmp policy
327
                    fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromId(key, session);
337
                    fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstanceFromId(key, session);
Lines 397-411 Link Here
397
407
398
    /**
408
    /**
399
     * INTERNAL:
409
     * INTERNAL:
400
     * Use the key to create a EclipseLink primary key Vector.
410
     * Use the key to create a EclipseLink primary key.
401
     * If the key is simple (direct mapped) then just add it to a vector,
411
     * If the key is simple (direct mapped) then just add it to a vector,
402
     * otherwise must go through the inefficient process of copying the key into the bean
412
     * otherwise must go through the inefficient process of copying the key into the bean
403
     * and extracting the key from the bean.
413
     * and extracting the key from the bean.
404
     *
405
     * @param key Object the primary key to use for creating the vector
406
     * @return Vector
407
     */
414
     */
408
    public Vector createPkVectorFromKey(Object key, AbstractSession session) {
415
    public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
409
        // TODO fix this exception so that it is more descriptive
416
        // TODO fix this exception so that it is more descriptive
410
        // This method only works in CMP3Policy but was added here for separation
417
        // This method only works in CMP3Policy but was added here for separation
411
        // of components
418
        // of components
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/DescriptorEvent.java (+1 lines)
Lines 334-339 Link Here
334
        }
334
        }
335
        if (eventChangeSet != null) {
335
        if (eventChangeSet != null) {
336
            eventChangeSet.removeChange(attributeName);
336
            eventChangeSet.removeChange(attributeName);
337
            // TODO: Can't see this working with attribute change tracking with no backup clone.
337
            eventChangeSet.addChange(mapping.compareForChange(clone, ((UnitOfWorkImpl)getSession()).getBackupClone(clone, getDescriptor()), eventChangeSet, getSession()));
338
            eventChangeSet.addChange(mapping.compareForChange(clone, ((UnitOfWorkImpl)getSession()).getBackupClone(clone, getDescriptor()), eventChangeSet, getSession()));
338
            eventChangeSet.setShouldRecalculateAfterUpdateEvent(false);
339
            eventChangeSet.setShouldRecalculateAfterUpdateEvent(false);
339
        }
340
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/InheritancePolicy.java (-41 / +33 lines)
Lines 50-56 Link Here
50
    protected Class parentClass;
50
    protected Class parentClass;
51
    protected String parentClassName;
51
    protected String parentClassName;
52
    protected ClassDescriptor parentDescriptor;
52
    protected ClassDescriptor parentDescriptor;
53
    protected Vector childDescriptors;
53
    protected List<ClassDescriptor> childDescriptors;
54
    protected transient DatabaseField classIndicatorField;
54
    protected transient DatabaseField classIndicatorField;
55
    protected transient Map classIndicatorMapping;
55
    protected transient Map classIndicatorMapping;
56
    protected transient Map classNameIndicatorMapping;
56
    protected transient Map classNameIndicatorMapping;
Lines 58-72 Link Here
58
    protected transient Boolean shouldReadSubclasses;
58
    protected transient Boolean shouldReadSubclasses;
59
    protected transient boolean hasMultipleTableChild;
59
    protected transient boolean hasMultipleTableChild;
60
    protected transient DatabaseTable readAllSubclassesView;
60
    protected transient DatabaseTable readAllSubclassesView;
61
    protected transient Vector allChildClassIndicators;
61
    protected transient List<Object> allChildClassIndicators;
62
    protected transient Expression onlyInstancesExpression;
62
    protected transient Expression onlyInstancesExpression;
63
    protected transient Expression withAllSubclassesExpression;
63
    protected transient Expression withAllSubclassesExpression;
64
    // null if there are no childrenTables, otherwise all tables for reference class plus childrenTables
64
    // null if there are no childrenTables, otherwise all tables for reference class plus childrenTables
65
    protected transient Vector allTables;
65
    protected transient Vector allTables;
66
    // all tables for all subclasses (subclasses of subclasses included), should be in sync with childrenTablesJoinExpressions.
66
    // all tables for all subclasses (subclasses of subclasses included), should be in sync with childrenTablesJoinExpressions.
67
    protected transient List childrenTables;
67
    protected transient List<DatabaseTable> childrenTables;
68
    // join expression for each child table, keyed by the table, should be in sync with childrenTables.
68
    // join expression for each child table, keyed by the table, should be in sync with childrenTables.
69
    protected transient Map childrenTablesJoinExpressions;
69
    protected transient Map<DatabaseTable, Expression> childrenTablesJoinExpressions;
70
    // all expressions from childrenTablesJoinExpressions ANDed together
70
    // all expressions from childrenTablesJoinExpressions ANDed together
71
    protected transient Expression childrenJoinExpression;
71
    protected transient Expression childrenJoinExpression;
72
72
Lines 100-107 Link Here
100
        this.classIndicatorMapping = new HashMap(10);
100
        this.classIndicatorMapping = new HashMap(10);
101
        this.classNameIndicatorMapping = new HashMap(10);
101
        this.classNameIndicatorMapping = new HashMap(10);
102
        this.shouldUseClassNameAsIndicator = false;
102
        this.shouldUseClassNameAsIndicator = false;
103
        this.allChildClassIndicators = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
103
        this.allChildClassIndicators = new ArrayList(4);
104
        this.childDescriptors = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(5);
104
        this.childDescriptors = new ArrayList(4);
105
        this.setJoinedStrategy();
105
        this.setJoinedStrategy();
106
    }
106
    }
107
107
Lines 120-126 Link Here
120
     * Add child descriptor to the parent descriptor.
120
     * Add child descriptor to the parent descriptor.
121
     */
121
     */
122
    public void addChildDescriptor(ClassDescriptor childDescriptor) {
122
    public void addChildDescriptor(ClassDescriptor childDescriptor) {
123
        getChildDescriptors().addElement(childDescriptor);
123
        getChildDescriptors().add(childDescriptor);
124
    }
124
    }
125
125
126
    /**
126
    /**
Lines 129-145 Link Here
129
     * are created simultaneously and kept in sync.
129
     * are created simultaneously and kept in sync.
130
     */
130
     */
131
    protected void addChildTableJoinExpression(DatabaseTable table, Expression expression) {
131
    protected void addChildTableJoinExpression(DatabaseTable table, Expression expression) {
132
        if(childrenTablesJoinExpressions == null) {
132
        if (this.childrenTablesJoinExpressions == null) {
133
           childrenTablesJoinExpressions = new HashMap();
133
            this.childrenTablesJoinExpressions = new HashMap();
134
           // childrenTables should've been null, too
134
           // childrenTables should've been null, too
135
           childrenTables = new ArrayList();
135
            this.childrenTables = new ArrayList();
136
           // allTables should've been null, too
136
           // allTables should've been null, too
137
           allTables = new Vector(getDescriptor().getTables());
137
            this.allTables = new Vector(getDescriptor().getTables());
138
        }
138
        }
139
        childrenTables.add(table);
139
        this.childrenTables.add(table);
140
        allTables.add(table);
140
        this.allTables.add(table);
141
        childrenTablesJoinExpressions.put(table, expression);
141
        this.childrenTablesJoinExpressions.put(table, expression);
142
        childrenJoinExpression = expression.and(childrenJoinExpression);
142
        this.childrenJoinExpression = expression.and(this.childrenJoinExpression);
143
    }
143
    }
144
144
145
    /**
145
    /**
Lines 221-227 Link Here
221
221
222
        if (parentDescriptor.getInheritancePolicy().isChildDescriptor()) {
222
        if (parentDescriptor.getInheritancePolicy().isChildDescriptor()) {
223
            if (parentDescriptor.getInheritancePolicy().shouldReadSubclasses()) {
223
            if (parentDescriptor.getInheritancePolicy().shouldReadSubclasses()) {
224
                parentDescriptor.getInheritancePolicy().getAllChildClassIndicators().addElement(indicator);
224
                parentDescriptor.getInheritancePolicy().getAllChildClassIndicators().add(indicator);
225
            }
225
            }
226
            parentDescriptor.getInheritancePolicy().addClassIndicatorTypeToParent(indicator);
226
            parentDescriptor.getInheritancePolicy().addClassIndicatorTypeToParent(indicator);
227
        }
227
        }
Lines 481-487 Link Here
481
     * Stores class indicators for all child and children's children.
481
     * Stores class indicators for all child and children's children.
482
     * Used for queries on branch classes only.
482
     * Used for queries on branch classes only.
483
     */
483
     */
484
    protected Vector getAllChildClassIndicators() {
484
    protected List<Object> getAllChildClassIndicators() {
485
        return allChildClassIndicators;
485
        return allChildClassIndicators;
486
    }
486
    }
487
487
Lines 491-499 Link Here
491
     * subclasses.
491
     * subclasses.
492
     * Required for bug 3019934.
492
     * Required for bug 3019934.
493
     */
493
     */
494
    public Vector getAllChildDescriptors() {
494
    public List<ClassDescriptor> getAllChildDescriptors() {
495
        // Guess the number of child descriptors...
495
        // Guess the number of child descriptors...
496
        Vector allChildDescriptors = new Vector(this.getAllChildClassIndicators().size());
496
        List<ClassDescriptor> allChildDescriptors = new ArrayList(this.getAllChildClassIndicators().size());
497
        return getAllChildDescriptors(allChildDescriptors);
497
        return getAllChildDescriptors(allChildDescriptors);
498
    }
498
    }
499
499
Lines 501-510 Link Here
501
     * INTERNAL:
501
     * INTERNAL:
502
     * Recursive subroutine of getAllChildDescriptors.
502
     * Recursive subroutine of getAllChildDescriptors.
503
     */
503
     */
504
    protected Vector getAllChildDescriptors(Vector allChildDescriptors) {
504
    protected List<ClassDescriptor> getAllChildDescriptors(List<ClassDescriptor> allChildDescriptors) {
505
        for (Enumeration enumtr = getChildDescriptors().elements(); enumtr.hasMoreElements();) {
505
        for (ClassDescriptor childDescriptor : getChildDescriptors()) {
506
            ClassDescriptor childDescriptor = (ClassDescriptor)enumtr.nextElement();
506
            allChildDescriptors.add(childDescriptor);
507
            allChildDescriptors.addElement(childDescriptor);
508
            childDescriptor.getInheritancePolicyOrNull().getAllChildDescriptors(allChildDescriptors);
507
            childDescriptor.getInheritancePolicyOrNull().getAllChildDescriptors(allChildDescriptors);
509
        }
508
        }
510
        return allChildDescriptors;
509
        return allChildDescriptors;
Lines 514-520 Link Here
514
     * INTERNAL:
513
     * INTERNAL:
515
     * if reads subclasses, all tables for all read subclasses (indirect included).
514
     * if reads subclasses, all tables for all read subclasses (indirect included).
516
     */
515
     */
517
    public List getChildrenTables() {
516
    public List<DatabaseTable> getChildrenTables() {
518
        return childrenTables;
517
        return childrenTables;
519
    }
518
    }
520
    
519
    
Lines 522-528 Link Here
522
     * INTERNAL:
521
     * INTERNAL:
523
     * join expression for each child table, keyed by the table
522
     * join expression for each child table, keyed by the table
524
     */
523
     */
525
    public Map getChildrenTablesJoinExpressions() {
524
    public Map<DatabaseTable, Expression> getChildrenTablesJoinExpressions() {
526
        return childrenTablesJoinExpressions;
525
        return childrenTablesJoinExpressions;
527
    }
526
    }
528
    
527
    
Lines 539-545 Link Here
539
     * all tables for reference class plus childrenTables
538
     * all tables for reference class plus childrenTables
540
     */
539
     */
541
    public Vector getAllTables() {
540
    public Vector getAllTables() {
542
        if(allTables == null) {
541
        if (allTables == null) {
543
            return this.getDescriptor().getTables();
542
            return this.getDescriptor().getTables();
544
        } else {
543
        } else {
545
            return allTables;
544
            return allTables;
Lines 551-557 Link Here
551
     * Return all the immediate child descriptors.  Only descriptors from
550
     * Return all the immediate child descriptors.  Only descriptors from
552
     * direct subclasses are returned.
551
     * direct subclasses are returned.
553
     */
552
     */
554
    public Vector getChildDescriptors() {
553
    public List<ClassDescriptor> getChildDescriptors() {
555
        return childDescriptors;
554
        return childDescriptors;
556
    }
555
    }
557
556
Lines 943-949 Link Here
943
942
944
            if (getClassIndicatorValue() != null) {
943
            if (getClassIndicatorValue() != null) {
945
                if (shouldReadSubclasses()) {
944
                if (shouldReadSubclasses()) {
946
                    getAllChildClassIndicators().addElement(getClassIndicatorValue());
945
                    getAllChildClassIndicators().add(getClassIndicatorValue());
947
                }
946
                }
948
                addClassIndicatorTypeToParent(getClassIndicatorValue());
947
                addClassIndicatorTypeToParent(getClassIndicatorValue());
949
            }
948
            }
Lines 1209-1217 Link Here
1209
        }
1208
        }
1210
1209
1211
        Vector tempChildren = new Vector(getChildDescriptors().size());
1210
        Vector tempChildren = new Vector(getChildDescriptors().size());
1212
        Enumeration childEnum = getChildDescriptors().elements();
1211
        for (ClassDescriptor childDescriptor : getChildDescriptors()) {
1213
        while (childEnum.hasMoreElements()) {
1214
            ClassDescriptor childDescriptor = (ClassDescriptor)childEnum.nextElement();
1215
            if (session.hasCorrespondingDescriptor(childDescriptor)) {
1212
            if (session.hasCorrespondingDescriptor(childDescriptor)) {
1216
                tempChildren.addElement(session.getDescriptor(childDescriptor.getJavaClass()));
1213
                tempChildren.addElement(session.getDescriptor(childDescriptor.getJavaClass()));
1217
            } else {
1214
            } else {
Lines 1254-1262 Link Here
1254
        }
1251
        }
1255
1252
1256
        // Recursively collect all rows from all concrete children and their children.
1253
        // Recursively collect all rows from all concrete children and their children.
1257
        for (Enumeration childrenEnum = getChildDescriptors().elements();
1254
        for (ClassDescriptor concreteDescriptor : getChildDescriptors()) {
1258
                 childrenEnum.hasMoreElements();) {
1259
            ClassDescriptor concreteDescriptor = (ClassDescriptor)childrenEnum.nextElement();
1260
            Vector concreteRows = concreteDescriptor.getInheritancePolicy().selectAllRowUsingCustomMultipleTableSubclassRead(query);
1255
            Vector concreteRows = concreteDescriptor.getInheritancePolicy().selectAllRowUsingCustomMultipleTableSubclassRead(query);
1261
            rows = Helper.concatenateVectors(rows, concreteRows);
1256
            rows = Helper.concatenateVectors(rows, concreteRows);
1262
        }
1257
        }
Lines 1281-1287 Link Here
1281
            AbstractRecord row = (AbstractRecord)rowsEnum.nextElement();
1276
            AbstractRecord row = (AbstractRecord)rowsEnum.nextElement();
1282
            Class concreteClass = classFromRow(row, query.getSession());
1277
            Class concreteClass = classFromRow(row, query.getSession());
1283
            if (!classes.contains(concreteClass)) {//Ensure unique ** we should do a distinct.. we do
1278
            if (!classes.contains(concreteClass)) {//Ensure unique ** we should do a distinct.. we do
1284
                classes.addElement(concreteClass);
1279
                classes.add(concreteClass);
1285
            }
1280
            }
1286
        }
1281
        }
1287
1282
Lines 1369-1379 Link Here
1369
        }
1364
        }
1370
1365
1371
        // Recursively collect all rows from all concrete children and their children.
1366
        // Recursively collect all rows from all concrete children and their children.
1372
        for (Enumeration childrenEnum = getChildDescriptors().elements();
1367
        for (ClassDescriptor concreteDescriptor : getChildDescriptors()) {
1373
                 childrenEnum.hasMoreElements();) {
1374
            ClassDescriptor concreteDescriptor = (ClassDescriptor)childrenEnum.nextElement();
1375
            AbstractRecord row = concreteDescriptor.getInheritancePolicy().selectOneRowUsingCustomMultipleTableSubclassRead(query);
1368
            AbstractRecord row = concreteDescriptor.getInheritancePolicy().selectOneRowUsingCustomMultipleTableSubclassRead(query);
1376
1377
            if (row != null) {
1369
            if (row != null) {
1378
                return row;
1370
                return row;
1379
            }
1371
            }
Lines 1434-1441 Link Here
1434
    /**
1426
    /**
1435
     * INTERNAL:
1427
     * INTERNAL:
1436
     */
1428
     */
1437
    public void setChildDescriptors(Vector theChildDescriptors) {
1429
    public void setChildDescriptors(List<ClassDescriptor> childDescriptors) {
1438
        childDescriptors = theChildDescriptors;
1430
        this.childDescriptors = childDescriptors;
1439
    }
1431
    }
1440
1432
1441
    /**
1433
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/VersionLockingPolicy.java (+3 lines)
Lines 349-354 Link Here
349
    public Object getWriteLockValue(Object domainObject, Object primaryKey, AbstractSession session) {
349
    public Object getWriteLockValue(Object domainObject, Object primaryKey, AbstractSession session) {
350
        Number writeLockFieldValue;
350
        Number writeLockFieldValue;
351
        if (isStoredInCache()) {
351
        if (isStoredInCache()) {
352
            if (primaryKey == null) {
353
                return null;
354
            }
352
            writeLockFieldValue = (Number)session.getIdentityMapAccessorInstance().getWriteLockValue(primaryKey, domainObject.getClass(), getDescriptor());
355
            writeLockFieldValue = (Number)session.getIdentityMapAccessorInstance().getWriteLockValue(primaryKey, domainObject.getClass(), getDescriptor());
353
        } else {
356
        } else {
354
            writeLockFieldValue = (Number)lockValueFromObject(domainObject);
357
            writeLockFieldValue = (Number)lockValueFromObject(domainObject);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/EISObjectPersistenceXMLProject.java (-2 / +2 lines)
Lines 387-394 Link Here
387
                    Iterator iterator = associations.iterator();
387
                    Iterator iterator = associations.iterator();
388
                    while (iterator.hasNext()) {
388
                    while (iterator.hasNext()) {
389
                        Association association = (Association)iterator.next();
389
                        Association association = (Association)iterator.next();
390
                        mapping.getSourceToTargetKeyFields().put(association.getKey(), association.getValue());
390
                        mapping.getSourceToTargetKeyFields().put((DatabaseField)association.getKey(), (DatabaseField)association.getValue());
391
                        mapping.getTargetToSourceKeyFields().put(association.getValue(), association.getKey());
391
                        mapping.getTargetToSourceKeyFields().put((DatabaseField)association.getValue(), (DatabaseField)association.getKey());
392
                    }
392
                    }
393
                }
393
                }
394
            });
394
            });
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/mappings/EISOneToManyMapping.java (-5 / +1 lines)
Lines 28-34 Link Here
28
import org.eclipse.persistence.expressions.Expression;
28
import org.eclipse.persistence.expressions.Expression;
29
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
29
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
30
import org.eclipse.persistence.internal.helper.DatabaseField;
30
import org.eclipse.persistence.internal.helper.DatabaseField;
31
import org.eclipse.persistence.internal.identitymaps.CacheKey;
32
import org.eclipse.persistence.internal.indirection.EISOneToManyQueryBasedValueHolder;
31
import org.eclipse.persistence.internal.indirection.EISOneToManyQueryBasedValueHolder;
33
import org.eclipse.persistence.oxm.XMLField;
32
import org.eclipse.persistence.oxm.XMLField;
34
import org.eclipse.persistence.internal.oxm.XPathEngine;
33
import org.eclipse.persistence.internal.oxm.XPathEngine;
Lines 709-718 Link Here
709
        Object primaryKey1 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element1, session);
708
        Object primaryKey1 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element1, session);
710
        Object primaryKey2 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element2, session);
709
        Object primaryKey2 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element2, session);
711
710
712
        CacheKey cacheKey1 = new CacheKey(primaryKey1);
711
        if (!primaryKey1.equals(primaryKey2)) {
713
        CacheKey cacheKey2 = new CacheKey(primaryKey2);
714
715
        if (!cacheKey1.equals(cacheKey2)) {
716
            return false;
712
            return false;
717
        }
713
        }
718
714
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/eis/mappings/EISOneToOneMapping.java (-104 / +46 lines)
Lines 17-29 Link Here
17
import java.util.Iterator;
17
import java.util.Iterator;
18
import java.util.List;
18
import java.util.List;
19
import java.util.Map;
19
import java.util.Map;
20
import java.util.Vector;
20
21
import org.eclipse.persistence.exceptions.ConversionException;
21
import org.eclipse.persistence.annotations.CacheKeyType;
22
import org.eclipse.persistence.exceptions.DatabaseException;
22
import org.eclipse.persistence.exceptions.DatabaseException;
23
import org.eclipse.persistence.exceptions.DescriptorException;
23
import org.eclipse.persistence.exceptions.DescriptorException;
24
import org.eclipse.persistence.expressions.Expression;
24
import org.eclipse.persistence.expressions.Expression;
25
import org.eclipse.persistence.expressions.ExpressionBuilder;
25
import org.eclipse.persistence.expressions.ExpressionBuilder;
26
import org.eclipse.persistence.internal.helper.DatabaseField;
26
import org.eclipse.persistence.internal.helper.DatabaseField;
27
import org.eclipse.persistence.internal.identitymaps.CacheId;
27
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
28
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
28
import org.eclipse.persistence.internal.sessions.AbstractRecord;
29
import org.eclipse.persistence.internal.sessions.AbstractRecord;
29
import org.eclipse.persistence.internal.sessions.AbstractSession;
30
import org.eclipse.persistence.internal.sessions.AbstractSession;
Lines 35-41 Link Here
35
 * <p>An EIS one-to-one mapping is a reference mapping that represents the relationship between 
36
 * <p>An EIS one-to-one mapping is a reference mapping that represents the relationship between 
36
 * a single source object and a single mapped persistent Java object.  The source object usually 
37
 * a single source object and a single mapped persistent Java object.  The source object usually 
37
 * contains a foreign key (pointer) to the target object (key on source); alternatively, the target 
38
 * contains a foreign key (pointer) to the target object (key on source); alternatively, the target 
38
 * object may contiain a foreign key to the source object (key on target).  Because both the source 
39
 * object may contain a foreign key to the source object (key on target).  Because both the source 
39
 * and target objects use interactions, they must both be configured as root object types.  
40
 * and target objects use interactions, they must both be configured as root object types.  
40
 * 
41
 * 
41
 * <p><table border="1">
42
 * <p><table border="1">
Lines 72-78 Link Here
72
    protected Map sourceToTargetKeyFields;
73
    protected Map sourceToTargetKeyFields;
73
74
74
    /** Maps the target primary/foreign key fields to the source foreign/primary key fields. */
75
    /** Maps the target primary/foreign key fields to the source foreign/primary key fields. */
75
    protected Map targetToSourceKeyFields;
76
    protected Map<DatabaseField, DatabaseField> targetToSourceKeyFields;
76
77
77
    /** These are used for non-unit of work modification to check if the value of the 1-1 was changed and a deletion is required. */
78
    /** These are used for non-unit of work modification to check if the value of the 1-1 was changed and a deletion is required. */
78
    protected boolean shouldVerifyDelete;
79
    protected boolean shouldVerifyDelete;
Lines 90-95 Link Here
90
    /**
91
    /**
91
     * INTERNAL:
92
     * INTERNAL:
92
     */
93
     */
94
    @Override
93
    public boolean isEISMapping() {
95
    public boolean isEISMapping() {
94
        return true;
96
        return true;
95
    }
97
    }
Lines 97-119 Link Here
97
    /**
99
    /**
98
     * INTERNAL:
100
     * INTERNAL:
99
     */
101
     */
102
    @Override
100
    public boolean isOneToOneMapping() {
103
    public boolean isOneToOneMapping() {
101
        return true;
104
        return true;
102
    }
105
    }
103
106
104
    /**
107
    /**
105
         * PUBLIC:
108
     * PUBLIC:
106
         * Define the source foreign key relationship in the one-to-one mapping.
109
     * Define the source foreign key relationship in the one-to-one mapping.
107
         * This method is used to add foreign key relationships to the mapping.
110
     * This method is used to add foreign key relationships to the mapping.
108
         * Both the source foreign key field name and the corresponding
111
     * Both the source foreign key field name and the corresponding
109
         * target primary key field name must be specified.
112
     * target primary key field name must be specified.
110
         */
113
     */
111
    public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetKeyField) {
114
    public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetKeyField) {
112
        this.getSourceToTargetKeyFields().put(sourceForeignKeyField, targetKeyField);
115
        getSourceToTargetKeyFields().put(sourceForeignKeyField, targetKeyField);
113
        this.getTargetToSourceKeyFields().put(targetKeyField, sourceForeignKeyField);
116
        getTargetToSourceKeyFields().put(targetKeyField, sourceForeignKeyField);
114
117
115
        this.getForeignKeyFields().add(sourceForeignKeyField);
118
        getForeignKeyFields().add(sourceForeignKeyField);
116
        this.setIsForeignKeyRelationship(true);
119
        setIsForeignKeyRelationship(true);
117
    }
120
    }
118
121
119
    /**
122
    /**
Lines 132-137 Link Here
132
     * This methods clones all the fields and ensures that each collection refers to
135
     * This methods clones all the fields and ensures that each collection refers to
133
     * the same clones.
136
     * the same clones.
134
     */
137
     */
138
    @Override
135
    public Object clone() {
139
    public Object clone() {
136
        EISOneToOneMapping clone = (EISOneToOneMapping)super.clone();
140
        EISOneToOneMapping clone = (EISOneToOneMapping)super.clone();
137
        clone.setForeignKeyFields(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size()));
141
        clone.setForeignKeyFields(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size()));
Lines 151-157 Link Here
151
        Iterator sourceKeyIterator = getSourceToTargetKeyFields().keySet().iterator();
155
        Iterator sourceKeyIterator = getSourceToTargetKeyFields().keySet().iterator();
152
        while (sourceKeyIterator.hasNext()) {
156
        while (sourceKeyIterator.hasNext()) {
153
            DatabaseField sourceField = (DatabaseField)sourceKeyIterator.next();
157
            DatabaseField sourceField = (DatabaseField)sourceKeyIterator.next();
154
            DatabaseField targetField = (DatabaseField)getSourceToTargetKeyFields().get(sourceField);
158
            DatabaseField targetField = getSourceToTargetKeyFields().get(sourceField);
155
159
156
            DatabaseField targetClone = (DatabaseField)setOfFields.get(targetField);
160
            DatabaseField targetClone = (DatabaseField)setOfFields.get(targetField);
157
            if (targetClone == null) {
161
            if (targetClone == null) {
Lines 171-177 Link Here
171
        Iterator targetKeyIterator = getTargetToSourceKeyFields().keySet().iterator();
175
        Iterator targetKeyIterator = getTargetToSourceKeyFields().keySet().iterator();
172
        while (targetKeyIterator.hasNext()) {
176
        while (targetKeyIterator.hasNext()) {
173
            DatabaseField targetField = (DatabaseField)targetKeyIterator.next();
177
            DatabaseField targetField = (DatabaseField)targetKeyIterator.next();
174
            DatabaseField sourceField = (DatabaseField)getTargetToSourceKeyFields().get(targetField);
178
            DatabaseField sourceField = getTargetToSourceKeyFields().get(targetField);
175
179
176
            DatabaseField targetClone = (DatabaseField)setOfFields.get(targetField);
180
            DatabaseField targetClone = (DatabaseField)setOfFields.get(targetField);
177
            if (targetClone == null) {
181
            if (targetClone == null) {
Lines 192-263 Link Here
192
196
193
    /**
197
    /**
194
     * INTERNAL:
198
     * INTERNAL:
195
     * Extract the foreign key value from the source row.
196
     */
197
    protected Vector extractForeignKeyFromRow(AbstractRecord row, AbstractSession session) {
198
        Vector key = new Vector();
199
200
        Iterator sourceKeyIterator = getSourceToTargetKeyFields().keySet().iterator();
201
        while (sourceKeyIterator.hasNext()) {
202
            DatabaseField field = (DatabaseField)sourceKeyIterator.next();
203
            Object value = row.get(field);
204
205
            // Must ensure the classification gets a cache hit.
206
            try {
207
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
208
            } catch (ConversionException e) {
209
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
210
            }
211
212
            key.addElement(value);
213
        }
214
215
        return key;
216
    }
217
218
    /**
219
     * INTERNAL:
220
     * Extract the key value from the reference object.
221
     */
222
    protected Vector extractKeyFromReferenceObject(Object object, AbstractSession session) {
223
        Vector key = new Vector();
224
225
        Iterator sourceKeyIterator = getSourceToTargetKeyFields().keySet().iterator();
226
        while (sourceKeyIterator.hasNext()) {
227
            DatabaseField field = (DatabaseField)sourceKeyIterator.next();
228
            if (object == null) {
229
                key.addElement(null);
230
            } else {
231
                key.addElement(getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, field, session));
232
            }
233
        }
234
        return key;
235
    }
236
237
    /**
238
     * INTERNAL:
239
     * Return the primary key for the reference object (i.e. the object
199
     * Return the primary key for the reference object (i.e. the object
240
     * object referenced by domainObject and specified by mapping).
200
     * object referenced by domainObject and specified by mapping).
241
     * This key will be used by a RemoteValueHolder.
201
     * This key will be used by a RemoteValueHolder.
242
     */
202
     */
243
    public Vector extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
203
    @Override
204
    public Object extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
244
        List primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
205
        List primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
245
        Vector result = new Vector(primaryKeyFields.size());
206
        Object[] result = new  Object[primaryKeyFields.size()];
246
        for (int index = 0; index < primaryKeyFields.size(); index++) {
207
        for (int index = 0; index < primaryKeyFields.size(); index++) {
247
            DatabaseField targetKeyField = (DatabaseField)primaryKeyFields.get(index);
208
            DatabaseField targetKeyField = (DatabaseField)primaryKeyFields.get(index);
248
            DatabaseField sourceKeyField = (DatabaseField)getTargetToSourceKeyFields().get(targetKeyField);
209
            DatabaseField sourceKeyField = getTargetToSourceKeyFields().get(targetKeyField);
249
            if (sourceKeyField == null) {
210
            if (sourceKeyField == null) {
250
                return new Vector(1);
211
                return null;
251
            }
212
            }
252
            result.addElement(row.get(sourceKeyField));
213
            result[index] = row.get(sourceKeyField);
214
            if (getReferenceDescriptor().getCacheKeyType() == CacheKeyType.ID_VALUE) {
215
                return result[index];
216
            }
253
        }
217
        }
254
        return result;
218
        return new CacheId(result);
255
    }
219
    }
256
220
257
    /**
221
    /**
258
     * INTERNAL:
222
     * INTERNAL:
259
     * Initialize the mapping.
223
     * Initialize the mapping.
260
     */
224
     */
225
    @Override
261
    public void initialize(AbstractSession session) throws DescriptorException {
226
    public void initialize(AbstractSession session) throws DescriptorException {
262
        super.initialize(session);
227
        super.initialize(session);
263
228
Lines 320-326 Link Here
320
        Iterator keyIterator = getSourceToTargetKeyFields().keySet().iterator();
285
        Iterator keyIterator = getSourceToTargetKeyFields().keySet().iterator();
321
        while (keyIterator.hasNext()) {
286
        while (keyIterator.hasNext()) {
322
            DatabaseField foreignKey = (DatabaseField)keyIterator.next();
287
            DatabaseField foreignKey = (DatabaseField)keyIterator.next();
323
            DatabaseField targetKey = (DatabaseField)getSourceToTargetKeyFields().get(foreignKey);
288
            DatabaseField targetKey = getSourceToTargetKeyFields().get(foreignKey);
324
289
325
            Expression expression = builder.getField(targetKey).equal(builder.getParameter(foreignKey));
290
            Expression expression = builder.getField(targetKey).equal(builder.getParameter(foreignKey));
326
            criteria = expression.and(getSelectionCriteria());
291
            criteria = expression.and(getSelectionCriteria());
Lines 332-337 Link Here
332
     * INTERNAL:
297
     * INTERNAL:
333
     * Reads the private owned object.
298
     * Reads the private owned object.
334
     */
299
     */
300
    @Override
335
    protected Object readPrivateOwnedForObject(ObjectLevelModifyQuery modifyQuery) throws DatabaseException {
301
    protected Object readPrivateOwnedForObject(ObjectLevelModifyQuery modifyQuery) throws DatabaseException {
336
        if (modifyQuery.getSession().isUnitOfWork()) {
302
        if (modifyQuery.getSession().isUnitOfWork()) {
337
            return getRealAttributeValueFromObject(modifyQuery.getBackupClone(), modifyQuery.getSession());
303
            return getRealAttributeValueFromObject(modifyQuery.getBackupClone(), modifyQuery.getSession());
Lines 378-383 Link Here
378
     * Return the value of the field from the row or a value holder on the query to obtain the object.
344
     * Return the value of the field from the row or a value holder on the query to obtain the object.
379
     * Check for batch + aggregation reading.
345
     * Check for batch + aggregation reading.
380
     */
346
     */
347
    @Override
381
    public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession session) throws DatabaseException {
348
    public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession session) throws DatabaseException {
382
        // If any field in the foreign key is null then it means there are no referenced objects
349
        // If any field in the foreign key is null then it means there are no referenced objects
383
        // Skip for partial objects as fk may not be present.
350
        // Skip for partial objects as fk may not be present.
Lines 415-420 Link Here
415
     * INTERNAL:
382
     * INTERNAL:
416
     * Get a value from the object and set that in the respective field of the row.
383
     * Get a value from the object and set that in the respective field of the row.
417
     */
384
     */
385
    @Override
418
    public void writeFromObjectIntoRow(Object object, AbstractRecord Record, AbstractSession session) {
386
    public void writeFromObjectIntoRow(Object object, AbstractRecord Record, AbstractSession session) {
419
        if (isReadOnly() || (!isForeignKeyRelationship())) {
387
        if (isReadOnly() || (!isForeignKeyRelationship())) {
420
            return;
388
            return;
Lines 427-433 Link Here
427
395
428
            for (int i = 0; i < getForeignKeyFields().size(); i++) {
396
            for (int i = 0; i < getForeignKeyFields().size(); i++) {
429
                DatabaseField sourceKey = getForeignKeyFields().get(i);
397
                DatabaseField sourceKey = getForeignKeyFields().get(i);
430
                DatabaseField targetKey = (DatabaseField)getSourceToTargetKeyFields().get(sourceKey);
398
                DatabaseField targetKey = getSourceToTargetKeyFields().get(sourceKey);
431
399
432
                Object referenceValue = null;
400
                Object referenceValue = null;
433
401
Lines 450-457 Link Here
450
     * Return the classifiction for the field contained in the mapping.
418
     * Return the classifiction for the field contained in the mapping.
451
     * This is used to convert the row value to a consistent java value.
419
     * This is used to convert the row value to a consistent java value.
452
     */
420
     */
421
    @Override
453
    public Class getFieldClassification(DatabaseField fieldToClassify) throws DescriptorException {
422
    public Class getFieldClassification(DatabaseField fieldToClassify) throws DescriptorException {
454
        DatabaseField fieldInTarget = (DatabaseField)getSourceToTargetKeyFields().get(fieldToClassify);
423
        DatabaseField fieldInTarget = getSourceToTargetKeyFields().get(fieldToClassify);
455
        if (fieldInTarget == null) {
424
        if (fieldInTarget == null) {
456
            return null;// Can be registered as multiple table secondary field mapping
425
            return null;// Can be registered as multiple table secondary field mapping
457
        }
426
        }
Lines 507-513 Link Here
507
     * INTERNAL:
476
     * INTERNAL:
508
     * Gets the foreign key fields.
477
     * Gets the foreign key fields.
509
     */
478
     */
510
    public Map getSourceToTargetKeyFields() {
479
    public Map<DatabaseField, DatabaseField> getSourceToTargetKeyFields() {
511
        return sourceToTargetKeyFields;
480
        return sourceToTargetKeyFields;
512
    }
481
    }
513
482
Lines 515-521 Link Here
515
     * INTERNAL:
484
     * INTERNAL:
516
     * Gets the target foreign key fields.
485
     * Gets the target foreign key fields.
517
     */
486
     */
518
    public Map getTargetToSourceKeyFields() {
487
    public Map<DatabaseField, DatabaseField> getTargetToSourceKeyFields() {
519
        return targetToSourceKeyFields;
488
        return targetToSourceKeyFields;
520
    }
489
    }
521
490
Lines 539-544 Link Here
539
     * INTERNAL:
508
     * INTERNAL:
540
     * This method is not supported in an EIS environment.
509
     * This method is not supported in an EIS environment.
541
     */
510
     */
511
    @Override
542
    public void setSelectionSQLString(String sqlString) {
512
    public void setSelectionSQLString(String sqlString) {
543
        throw DescriptorException.invalidMappingOperation(this, "setSelectionSQLString");
513
        throw DescriptorException.invalidMappingOperation(this, "setSelectionSQLString");
544
    }
514
    }
Lines 547-593 Link Here
547
     * INTERNAL:
517
     * INTERNAL:
548
     * This method is not supported in an EIS environment.
518
     * This method is not supported in an EIS environment.
549
     */
519
     */
520
    @Override
550
    public void setUsesBatchReading(boolean usesBatchReading) {
521
    public void setUsesBatchReading(boolean usesBatchReading) {
551
        throw DescriptorException.invalidMappingOperation(this, "setUsesBatchReading");
522
        if (usesBatchReading) {
523
            throw DescriptorException.invalidMappingOperation(this, "setUsesBatchReading");
524
        }
552
    }
525
    }
553
526
554
    /**
527
    /**
555
     * INTERNAL:
528
     * INTERNAL:
556
     * This method is not supported in an EIS environment.
529
     * This method is not supported in an EIS environment.
557
     */
530
     */
558
    public boolean shouldUseBatchReading() {
531
    @Override
559
        throw DescriptorException.invalidMappingOperation(this, "shouldUseBatchReading");
560
    }
561
562
    /**
563
     * INTERNAL:
564
     * This method is not supported in an EIS environment.
565
     */
566
    public void useBatchReading() {
532
    public void useBatchReading() {
567
        throw DescriptorException.invalidMappingOperation(this, "useBatchReading");
533
        throw DescriptorException.invalidMappingOperation(this, "useBatchReading");
568
    }
534
    }
569
570
    /**
571
     * INTERNAL:
572
     * This method is not supported in an EIS environment.
573
     */
574
    public void dontUseBatchReading() {
575
        throw DescriptorException.invalidMappingOperation(this, "dontUseBatchReading");
576
    }
577
578
    /**
579
     * INTERNAL:
580
     * This method is not supported in an EIS environment.
581
     */
582
    public void addAscendingOrdering(String queryKeyName) {
583
        throw DescriptorException.invalidMappingOperation(this, "addAscendingOrdering");
584
    }
585
586
    /**
587
     * INTERNAL:
588
     * This method is not supported in an EIS environment.
589
     */
590
    public void addDescendingOrdering(String queryKeyName) {
591
        throw DescriptorException.invalidMappingOperation(this, "addDescendingOrdering");
592
    }
593
}
535
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/ObjectBuilder.java (-91 / +138 lines)
Lines 20-25 Link Here
20
import java.sql.ResultSetMetaData;
20
import java.sql.ResultSetMetaData;
21
import java.sql.SQLException;
21
import java.sql.SQLException;
22
22
23
import org.eclipse.persistence.annotations.CacheKeyType;
23
import org.eclipse.persistence.annotations.IdValidation;
24
import org.eclipse.persistence.annotations.IdValidation;
24
import org.eclipse.persistence.descriptors.ClassDescriptor;
25
import org.eclipse.persistence.descriptors.ClassDescriptor;
25
import org.eclipse.persistence.descriptors.DescriptorEvent;
26
import org.eclipse.persistence.descriptors.DescriptorEvent;
Lines 191-198 Link Here
191
    public void clearPrimaryKey(Object object) {
192
    public void clearPrimaryKey(Object object) {
192
        // PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key has changed.
193
        // PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key has changed.
193
        if (object instanceof PersistenceEntity) {
194
        if (object instanceof PersistenceEntity) {
194
            ((PersistenceEntity)object)._persistence_setPKVector(null);
195
            ((PersistenceEntity)object)._persistence_setId(null);
195
            ((PersistenceEntity)object)._persistence_setCacheKey(null);
196
        }
196
        }
197
    }
197
    }
198
198
Lines 702-709 Link Here
702
                }
702
                }
703
                // PERF: Cache the primary key and cache key if implements PersistenceEntity.
703
                // PERF: Cache the primary key and cache key if implements PersistenceEntity.
704
                if (domainObject instanceof PersistenceEntity) {
704
                if (domainObject instanceof PersistenceEntity) {
705
                    ((PersistenceEntity)domainObject)._persistence_setCacheKey(cacheKey);
705
                    ((PersistenceEntity)domainObject)._persistence_setId(primaryKey);
706
                    ((PersistenceEntity)domainObject)._persistence_setPKVector((Vector)primaryKey);
707
                }
706
                }
708
            } else {
707
            } else {
709
                if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
708
                if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
Lines 919-934 Link Here
919
     * Build the primary key expression from the specified primary key values.
918
     * Build the primary key expression from the specified primary key values.
920
     */
919
     */
921
    public Expression buildPrimaryKeyExpressionFromKeys(Object primaryKey, AbstractSession session) {
920
    public Expression buildPrimaryKeyExpressionFromKeys(Object primaryKey, AbstractSession session) {
922
        Expression expression = null;
923
        Expression subExpression;
924
        Expression builder = new ExpressionBuilder();
921
        Expression builder = new ExpressionBuilder();
925
        List primaryKeyFields = this.descriptor.getPrimaryKeyFields();
922
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
926
923
927
        for (int index = 0; index < primaryKeyFields.size(); index++) {
924
        if (this.descriptor.getCacheKeyType() == CacheKeyType.ID_VALUE) {
928
            Object value = ((Vector)primaryKey).get(index);
925
            return builder.getField(primaryKeyFields.get(0)).equal(primaryKey);
929
            DatabaseField field = (DatabaseField)primaryKeyFields.get(index);
926
        }
927
        Expression expression = null;
928
        int size = primaryKeyFields.size();
929
        Object[] primaryKeyValues = ((CacheId)primaryKey).getPrimaryKey();
930
        for (int index = 0; index < size; index++) {
931
            Object value = primaryKeyValues[index];
932
            DatabaseField field = primaryKeyFields.get(index);
930
            if (value != null) {
933
            if (value != null) {
931
                subExpression = builder.getField(field).equal(value);
934
                Expression subExpression = builder.getField(field).equal(value);
932
                expression = subExpression.and(expression);
935
                expression = subExpression.and(expression);
933
            }
936
            }
934
        }
937
        }
Lines 1139-1158 Link Here
1139
    /**
1142
    /**
1140
     * Build the row from the primary key values.
1143
     * Build the row from the primary key values.
1141
     */
1144
     */
1142
    public AbstractRecord buildRowFromPrimaryKeyValues(Object key, AbstractSession session) {
1145
    public AbstractRecord writeIntoRowFromPrimaryKeyValues(AbstractRecord row, Object primaryKey, AbstractSession session, boolean convert) {
1143
        AbstractRecord databaseRow = createRecord(((Vector)key).size(), session);
1146
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
1144
        int keySize = ((Vector)key).size();
1147
        if (this.descriptor.getCacheKeyType() == CacheKeyType.ID_VALUE) {
1145
        for (int index = 0; index < keySize; index++) {
1148
            DatabaseField field = primaryKeyFields.get(0);
1146
            DatabaseField field = this.descriptor.getPrimaryKeyFields().get(index);
1149
            Object value = primaryKey;
1147
            Object value = ((Vector)key).get(index);
1148
            value = session.getPlatform(this.descriptor.getJavaClass()).getConversionManager().convertObject(value, field.getType());
1150
            value = session.getPlatform(this.descriptor.getJavaClass()).getConversionManager().convertObject(value, field.getType());
1149
            databaseRow.put(field, value);
1151
            row.put(field, value);
1152
            return row;
1150
        }
1153
        }
1154
        int size = primaryKeyFields.size();
1155
        Object[] primaryKeyValues = ((CacheId)primaryKey).getPrimaryKey();
1156
        for (int index = 0; index < size; index++) {
1157
            DatabaseField field = primaryKeyFields.get(index);
1158
            Object value = primaryKeyValues[index];
1159
            value = session.getPlatform(this.descriptor.getJavaClass()).getConversionManager().convertObject(value, field.getType());
1160
            row.put(field, value);
1161
        }
1151
1162
1152
        return databaseRow;
1163
        return row;
1153
    }
1164
    }
1154
1165
1155
    /**
1166
    /**
1167
     * Build the row from the primary key values.
1168
     */
1169
    public AbstractRecord buildRowFromPrimaryKeyValues(Object key, AbstractSession session) {
1170
        AbstractRecord databaseRow = createRecord(this.descriptor.getPrimaryKeyFields().size(), session);
1171
        return writeIntoRowFromPrimaryKeyValues(databaseRow, key, session, true);
1172
    }
1173
1174
    /**
1156
     * Build the row of all of the fields used for insertion.
1175
     * Build the row of all of the fields used for insertion.
1157
     */
1176
     */
1158
    public AbstractRecord buildTemplateInsertRow(AbstractSession session) {
1177
    public AbstractRecord buildTemplateInsertRow(AbstractSession session) {
Lines 1434-1440 Link Here
1434
            query.recordCloneForPessimisticLocking(workingClone, unitOfWork);
1453
            query.recordCloneForPessimisticLocking(workingClone, unitOfWork);
1435
            // PERF: Cache the primary key if implements PersistenceEntity.
1454
            // PERF: Cache the primary key if implements PersistenceEntity.
1436
            if (workingClone instanceof PersistenceEntity) {
1455
            if (workingClone instanceof PersistenceEntity) {
1437
                ((PersistenceEntity)workingClone)._persistence_setPKVector((Vector)primaryKey);
1456
                ((PersistenceEntity)workingClone)._persistence_setId(primaryKey);
1438
            }
1457
            }
1439
        } finally {
1458
        } finally {
1440
            unitOfWorkCacheKey.release();            
1459
            unitOfWorkCacheKey.release();            
Lines 1454-1462 Link Here
1454
    public Object buildObjectFromResultSet(ObjectBuildingQuery query, JoinedAttributeManager joinManager, ResultSet resultSet, AbstractSession executionSession, DatabaseAccessor accessor, ResultSetMetaData metaData, DatabasePlatform platform) throws SQLException {
1473
    public Object buildObjectFromResultSet(ObjectBuildingQuery query, JoinedAttributeManager joinManager, ResultSet resultSet, AbstractSession executionSession, DatabaseAccessor accessor, ResultSetMetaData metaData, DatabasePlatform platform) throws SQLException {
1455
        ClassDescriptor descriptor = this.descriptor;
1474
        ClassDescriptor descriptor = this.descriptor;
1456
        DatabaseMapping primaryKeyMapping = this.primaryKeyMappings.get(0);
1475
        DatabaseMapping primaryKeyMapping = this.primaryKeyMappings.get(0);
1457
        Object primaryKeyObject = primaryKeyMapping.valueFromResultSet(resultSet, query, executionSession, accessor, metaData, 1, platform);
1476
        Object primaryKey = primaryKeyMapping.valueFromResultSet(resultSet, query, executionSession, accessor, metaData, 1, platform);
1458
        Vector primaryKey = new NonSynchronizedVector(1);
1459
        primaryKey.add(primaryKeyObject);
1460
1477
1461
        UnitOfWorkImpl unitOfWork = null;
1478
        UnitOfWorkImpl unitOfWork = null;
1462
        AbstractSession session = executionSession;
1479
        AbstractSession session = executionSession;
Lines 1493-1499 Link Here
1493
                    }
1510
                    }
1494
                }
1511
                }
1495
                
1512
                
1496
                primaryKeyMapping.setAttributeValueInObject(object, primaryKeyObject);
1513
                primaryKeyMapping.setAttributeValueInObject(object, primaryKey);
1497
                List mappings = descriptor.getMappings();            
1514
                List mappings = descriptor.getMappings();            
1498
                int size = mappings.size();
1515
                int size = mappings.size();
1499
                for (int index = 1; index < size; index++) {
1516
                for (int index = 1; index < size; index++) {
Lines 1501-1507 Link Here
1501
                    mapping.readFromResultSetIntoObject(resultSet, object, query, session, accessor, metaData, index + 1, platform);
1518
                    mapping.readFromResultSetIntoObject(resultSet, object, query, session, accessor, metaData, index + 1, platform);
1502
                }
1519
                }
1503
                
1520
                
1504
                ((PersistenceEntity)object)._persistence_setPKVector(primaryKey);
1521
                ((PersistenceEntity)object)._persistence_setId(primaryKey);
1505
                if ((unitOfWork != null) && isolated) {
1522
                if ((unitOfWork != null) && isolated) {
1506
                    ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
1523
                    ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
1507
                    policy.setChangeListener(object, unitOfWork, descriptor);
1524
                    policy.setChangeListener(object, unitOfWork, descriptor);
Lines 1510-1516 Link Here
1510
            if ((unitOfWork != null) && !isolated) {
1527
            if ((unitOfWork != null) && !isolated) {
1511
                // Need to clone the object in the unit of work.
1528
                // Need to clone the object in the unit of work.
1512
                Object clone = instantiateWorkingCopyClone(object, unitOfWork);
1529
                Object clone = instantiateWorkingCopyClone(object, unitOfWork);
1513
                ((PersistenceEntity)clone)._persistence_setPKVector(cacheKey.getKey());
1530
                ((PersistenceEntity)clone)._persistence_setId(cacheKey.getKey());
1514
                unitOfWork.getCloneMapping().put(clone, clone);
1531
                unitOfWork.getCloneMapping().put(clone, clone);
1515
                unitOfWork.getCloneToOriginals().put(clone, object);
1532
                unitOfWork.getCloneToOriginals().put(clone, object);
1516
                cacheKey.setObject(clone);
1533
                cacheKey.setObject(clone);
Lines 1796-1802 Link Here
1796
        ObjectChangeSet changes = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(clone);
1813
        ObjectChangeSet changes = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(clone);
1797
        if (changes == null) {
1814
        if (changes == null) {
1798
            if (this.descriptor.isAggregateDescriptor()) {
1815
            if (this.descriptor.isAggregateDescriptor()) {
1799
                changes = new AggregateObjectChangeSet(new Vector(0), this.descriptor, clone, uowChangeSet, isNew);
1816
                changes = new AggregateObjectChangeSet(new CacheId(new Object[0]), this.descriptor, clone, uowChangeSet, isNew);
1800
            } else {
1817
            } else {
1801
                changes = new ObjectChangeSet(extractPrimaryKeyFromObject(clone, session, true), this.descriptor, clone, uowChangeSet, isNew);
1818
                changes = new ObjectChangeSet(extractPrimaryKeyFromObject(clone, session, true), this.descriptor, clone, uowChangeSet, isNew);
1802
            }
1819
            }
Lines 1807-1813 Link Here
1807
                // If creating a new change set for a new object, the original change set (from change tracking) may have not had the primary key.
1824
                // If creating a new change set for a new object, the original change set (from change tracking) may have not had the primary key.
1808
                Object primaryKey = extractPrimaryKeyFromObject(clone, session, true);
1825
                Object primaryKey = extractPrimaryKeyFromObject(clone, session, true);
1809
                if (primaryKey != null) {
1826
                if (primaryKey != null) {
1810
                    changes.setCacheKey(new CacheKey(primaryKey));
1827
                    changes.setId(primaryKey);
1811
                }
1828
                }
1812
            }
1829
            }
1813
        }
1830
        }
Lines 1859-1865 Link Here
1859
            return null;
1876
            return null;
1860
        }
1877
        }
1861
1878
1862
        return extractPrimaryKeyFromRow(primaryKeyRow, session);
1879
        Object primaryKey = extractPrimaryKeyFromRow(primaryKeyRow, session);
1880
        if ((primaryKey == null) && isValid) {
1881
            return InvalidObject.instance;
1882
        }
1883
        return primaryKey;
1863
    }
1884
    }
1864
1885
1865
    /**
1886
    /**
Lines 1875-1883 Link Here
1875
    public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session, boolean shouldReturnNullIfNull) {
1896
    public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session, boolean shouldReturnNullIfNull) {
1876
        boolean isPersistenceEntity = domainObject instanceof PersistenceEntity;
1897
        boolean isPersistenceEntity = domainObject instanceof PersistenceEntity;
1877
        if (isPersistenceEntity) {
1898
        if (isPersistenceEntity) {
1878
            Vector key = ((PersistenceEntity)domainObject)._persistence_getPKVector();
1899
            Object primaryKey = ((PersistenceEntity)domainObject)._persistence_getId();
1879
            if (key != null) {
1900
            if (primaryKey != null) {
1880
                return key;
1901
                return primaryKey;
1881
            }
1902
            }
1882
        }
1903
        }
1883
        ClassDescriptor descriptor = this.descriptor;
1904
        ClassDescriptor descriptor = this.descriptor;
Lines 1885-1948 Link Here
1885
        // Allow for inheritance, the concrete descriptor must always be used.
1906
        // Allow for inheritance, the concrete descriptor must always be used.
1886
        if (descriptor.hasInheritance() && (domainObject.getClass() != descriptor.getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(descriptor.getJavaClass()))) {
1907
        if (descriptor.hasInheritance() && (domainObject.getClass() != descriptor.getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(descriptor.getJavaClass()))) {
1887
            return session.getDescriptor(domainObject).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session, shouldReturnNullIfNull);
1908
            return session.getDescriptor(domainObject).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session, shouldReturnNullIfNull);
1888
        } else {
1909
        }
1889
            IdValidation idValidation = descriptor.getIdValidation();
1910
        
1890
            List primaryKeyFields = descriptor.getPrimaryKeyFields();
1911
        IdValidation idValidation = descriptor.getIdValidation();
1891
            Vector primaryKeyValues = new NonSynchronizedVector(primaryKeyFields.size());
1912
        CacheKeyType cacheKeyType = descriptor.getCacheKeyType();
1913
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();        
1914
        Object[] primaryKeyValues = null;
1915
        if (cacheKeyType != CacheKeyType.ID_VALUE) {
1916
            primaryKeyValues = new Object[primaryKeyFields.size()];
1917
        }
1892
1918
1893
            List mappings = getPrimaryKeyMappings();
1919
        List<DatabaseMapping> mappings = getPrimaryKeyMappings();
1894
            int size = mappings.size();
1920
        int size = mappings.size();
1895
            // PERF: optimize simple case of direct mapped singleton primary key.
1921
        // PERF: optimize simple case of direct mapped singleton primary key.
1896
            if (descriptor.hasSimplePrimaryKey()) {
1922
        if (descriptor.hasSimplePrimaryKey()) {
1897
                // PERF: use index not enumeration.
1923
            // PERF: use index not enumeration.
1898
                for (int index = 0; index < size; index++) {
1924
            for (int index = 0; index < size; index++) {
1899
                    AbstractDirectMapping mapping = (AbstractDirectMapping)mappings.get(index);
1925
                AbstractDirectMapping mapping = (AbstractDirectMapping)mappings.get(index);
1900
                    Object keyValue = mapping.valueFromObject(domainObject, (DatabaseField)primaryKeyFields.get(index), session);
1926
                Object keyValue = mapping.valueFromObject(domainObject, primaryKeyFields.get(index), session);
1901
                    // Only check for 0 for singleton primary keys.
1927
                // Only check for 0 for singleton primary keys.
1902
                    if ((idValidation != IdValidation.NONE) && ((keyValue == null)
1928
                if ((idValidation != IdValidation.NONE) && ((keyValue == null)
1903
                                || ((idValidation == IdValidation.ZERO) && Helper.isEquivalentToNull(keyValue)))) {
1929
                            || ((idValidation == IdValidation.ZERO) && Helper.isEquivalentToNull(keyValue)))) {
1904
                        if (shouldReturnNullIfNull) {
1930
                    if (shouldReturnNullIfNull) {
1905
                            return null;
1931
                        return null;
1906
                        }
1907
                        isNull = true;
1908
                    }
1932
                    }
1909
                    primaryKeyValues.add(keyValue);
1933
                    isNull = true;
1910
                }
1934
                }
1911
            } else {
1935
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
1912
                AbstractRecord databaseRow = createRecordForPKExtraction(size, session);
1936
                    if (isPersistenceEntity && (!isNull)) {
1913
                // PERF: use index not enumeration			
1937
                        ((PersistenceEntity)domainObject)._persistence_setId(keyValue);
1914
                for (int index = 0; index < size; index++) {
1915
                    DatabaseMapping mapping = (DatabaseMapping)mappings.get(index);
1916
                    // Primary key mapping may be null for aggregate collection.
1917
                    if (mapping != null) {
1918
                        mapping.writeFromObjectIntoRow(domainObject, databaseRow, session);
1919
                    }
1938
                    }
1939
                    return keyValue;
1940
                } else {
1941
                    primaryKeyValues[index] = keyValue;
1920
                }
1942
                }
1921
                List primaryKeyClassifications = getPrimaryKeyClassifications();
1943
            }
1922
                Platform platform = session.getPlatform(domainObject.getClass());
1944
        } else {
1923
                // PERF: use index not enumeration			
1945
            AbstractRecord databaseRow = createRecordForPKExtraction(size, session);
1924
                for (int index = 0; index < size; index++) {
1946
            // PERF: use index not enumeration			
1925
                    // Ensure that the type extracted from the object is the same type as in the descriptor,
1947
            for (int index = 0; index < size; index++) {
1926
                    // the main reason for this is that 1-1 can optimize on vh by getting from the row as the row-type.
1948
                DatabaseMapping mapping = mappings.get(index);
1927
                    Class classification = (Class)primaryKeyClassifications.get(index);
1949
                // Primary key mapping may be null for aggregate collection.
1928
                    Object value = databaseRow.get((DatabaseField)primaryKeyFields.get(index));
1950
                if (mapping != null) {
1929
                    // Only check for 0 for singleton primary keys.
1951
                    mapping.writeFromObjectIntoRow(domainObject, databaseRow, session);
1930
                    if ((idValidation != IdValidation.NONE) && ((value == null)
1952
                }
1931
                            || ((idValidation == IdValidation.ZERO) && Helper.isEquivalentToNull(value)))) {
1953
            }
1932
                        if (shouldReturnNullIfNull) {
1954
            List<Class> primaryKeyClassifications = getPrimaryKeyClassifications();
1933
                            return null;
1955
            Platform platform = session.getPlatform(domainObject.getClass());
1934
                        }
1956
            // PERF: use index not enumeration
1935
                        isNull = true;
1957
            for (int index = 0; index < size; index++) {
1958
                // Ensure that the type extracted from the object is the same type as in the descriptor,
1959
                // the main reason for this is that 1-1 can optimize on vh by getting from the row as the row-type.
1960
                Class classification = primaryKeyClassifications.get(index);
1961
                Object value = databaseRow.get(primaryKeyFields.get(index));
1962
                // Only check for 0 for singleton primary keys.
1963
                if ((idValidation != IdValidation.NONE) && ((value == null)
1964
                        || ((idValidation == IdValidation.ZERO) && Helper.isEquivalentToNull(value)))) {
1965
                    if (shouldReturnNullIfNull) {
1966
                        return null;
1936
                    }
1967
                    }
1937
                    // CR2114 following line modified; domainObject.getClass() passed as an argument
1968
                    isNull = true;
1938
                    primaryKeyValues.add(platform.convertObject(value, classification));
1939
                }
1969
                }
1970
                value = platform.convertObject(value, classification);
1971
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
1972
                    if (isPersistenceEntity && (!isNull)) {
1973
                        ((PersistenceEntity)domainObject)._persistence_setId(value);
1974
                    }
1975
                    return value;
1976
                } else {
1977
                    primaryKeyValues[index] = value;
1978
                }
1940
            }
1979
            }
1941
            if (isPersistenceEntity && (!isNull)) {
1942
                ((PersistenceEntity)domainObject)._persistence_setPKVector(primaryKeyValues);
1943
            }
1944
            return primaryKeyValues;
1945
        }
1980
        }
1981
        CacheId id = new CacheId(primaryKeyValues);
1982
        if (isPersistenceEntity && (!isNull)) {
1983
            ((PersistenceEntity)domainObject)._persistence_setId(id);
1984
        }
1985
        return id;
1946
    }
1986
    }
1947
1987
1948
    /**
1988
    /**
Lines 1950-1978 Link Here
1950
     * null is returned if the row does not contain the key.
1990
     * null is returned if the row does not contain the key.
1951
     */
1991
     */
1952
    public Object extractPrimaryKeyFromRow(AbstractRecord databaseRow, AbstractSession session) {
1992
    public Object extractPrimaryKeyFromRow(AbstractRecord databaseRow, AbstractSession session) {
1953
        List primaryKeyFields = this.descriptor.getPrimaryKeyFields();
1993
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
1954
        List primaryKeyClassifications = getPrimaryKeyClassifications();
1994
        List<Class> primaryKeyClassifications = getPrimaryKeyClassifications();
1955
        int size = primaryKeyFields.size();
1995
        int size = primaryKeyFields.size();
1956
        Vector primaryKeyValues = new NonSynchronizedVector(size);
1996
        Object[] primaryKeyValues = null;
1997
        CacheKeyType cacheKeyType = this.descriptor.getCacheKeyType();
1998
        if (cacheKeyType != CacheKeyType.ID_VALUE) {
1999
            primaryKeyValues = new Object[size];
2000
        }
1957
        int numberOfNulls = 0;
2001
        int numberOfNulls = 0;
1958
2002
1959
        // PERF: use index not enumeration
2003
        // PERF: use index not enumeration
1960
        for (int index = 0; index < size; index++) {
2004
        for (int index = 0; index < size; index++) {
1961
            DatabaseField field = (DatabaseField)primaryKeyFields.get(index);
2005
            DatabaseField field = primaryKeyFields.get(index);
1962
2006
1963
            // Ensure that the type extracted from the row is the same type as in the object.
2007
            // Ensure that the type extracted from the row is the same type as in the object.
1964
            Class classification = (Class)primaryKeyClassifications.get(index);
2008
            Class classification = primaryKeyClassifications.get(index);
1965
            Object value = databaseRow.get(field);
2009
            Object value = databaseRow.get(field);
1966
            if (value != null) {
2010
            if (value != null) {
1967
                if (value.getClass() != classification) {
2011
                if (value.getClass() != classification) {
1968
                    value = session.getPlatform(this.descriptor.getJavaClass()).convertObject(value, classification);
2012
                    value = session.getPlatform(this.descriptor.getJavaClass()).convertObject(value, classification);
1969
                }
2013
                }
1970
                primaryKeyValues.addElement(value);
2014
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
2015
                    return value;
2016
                }
2017
                primaryKeyValues[index] = value;
1971
            } else {
2018
            } else {
1972
                if(this.mayHaveNullInPrimaryKey) {
2019
                if (this.mayHaveNullInPrimaryKey) {
1973
                    numberOfNulls++;
2020
                    numberOfNulls++;
1974
                    if(numberOfNulls < size) {
2021
                    if (numberOfNulls < size) {
1975
                        primaryKeyValues.addElement(null);
2022
                        primaryKeyValues[index] = null;
1976
                    } else {
2023
                    } else {
1977
                        // Must have some non null elements. If all elements are null return null.
2024
                        // Must have some non null elements. If all elements are null return null.
1978
                        return null;
2025
                        return null;
Lines 1983-1989 Link Here
1983
            }
2030
            }
1984
        }
2031
        }
1985
2032
1986
        return primaryKeyValues;
2033
        return new CacheId(primaryKeyValues);
1987
    }
2034
    }
1988
2035
1989
    /**
2036
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/PersistenceEntity.java (-11 / +3 lines)
Lines 12-22 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.descriptors;
13
package org.eclipse.persistence.internal.descriptors;
14
14
15
16
import java.util.Vector;
17
18
import org.eclipse.persistence.internal.identitymaps.CacheKey;
19
20
/**
15
/**
21
 * Define an interface for utility methods weaved into the persistence classes.
16
 * Define an interface for utility methods weaved into the persistence classes.
22
 * These general methods are used to optimize performance, such as caching the key in the object.
17
 * These general methods are used to optimize performance, such as caching the key in the object.
Lines 25-34 Link Here
25
 * @author  mmacivor
20
 * @author  mmacivor
26
 * @since   10.1.3
21
 * @since   10.1.3
27
 */
22
 */
28
public interface PersistenceEntity {
23
public interface PersistenceEntity {    
29
    CacheKey _persistence_getCacheKey();
24
    Object _persistence_getId();
30
    void _persistence_setCacheKey(CacheKey key);
25
    void _persistence_setId(Object primaryKey);    
31
    
32
    Vector _persistence_getPKVector();
33
    void _persistence_setPKVector(Vector pk);    
34
}
26
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/dynamic/DynamicEntityImpl.java (-25 / +6 lines)
Lines 22-28 Link Here
22
import java.beans.PropertyChangeListener;
22
import java.beans.PropertyChangeListener;
23
import java.util.Collection;
23
import java.util.Collection;
24
import java.util.Map;
24
import java.util.Map;
25
import java.util.Vector;
26
25
27
//EclipseLink imports
26
//EclipseLink imports
28
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
27
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
Lines 33-39 Link Here
33
import org.eclipse.persistence.indirection.ValueHolderInterface;
32
import org.eclipse.persistence.indirection.ValueHolderInterface;
34
import org.eclipse.persistence.internal.descriptors.PersistenceEntity;
33
import org.eclipse.persistence.internal.descriptors.PersistenceEntity;
35
import org.eclipse.persistence.internal.helper.Helper;
34
import org.eclipse.persistence.internal.helper.Helper;
36
import org.eclipse.persistence.internal.identitymaps.CacheKey;
37
import org.eclipse.persistence.mappings.CollectionMapping;
35
import org.eclipse.persistence.mappings.CollectionMapping;
38
import org.eclipse.persistence.mappings.DatabaseMapping;
36
import org.eclipse.persistence.mappings.DatabaseMapping;
39
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
37
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
Lines 175-203 Link Here
175
173
176
    //PersistenceEntity API
174
    //PersistenceEntity API
177
    /**
175
    /**
178
     * Cache the CacheKey within the entity
179
     * 
180
     * @see PersistenceEntity#_persistence_setCacheKey(CacheKey)
181
     */
182
    private CacheKey cacheKey;
183
    /**
184
     * Cache the primary key within the entity
176
     * Cache the primary key within the entity
185
     * 
177
     * 
186
     * @see PersistenceEntity#_persistence_setPKVector(Vector)
178
     * @see PersistenceEntity#_persistence_setId(Object)
187
     */
179
     */
188
    private Vector<Object> primaryKey;
180
    private Object primaryKey;
189
    public CacheKey _persistence_getCacheKey() {
181
    
190
        return this.cacheKey;
191
    }
192
    public void _persistence_setCacheKey(CacheKey key) {
193
        this.cacheKey = key;
194
    }
195
    @SuppressWarnings("unchecked")
182
    @SuppressWarnings("unchecked")
196
    public Vector _persistence_getPKVector() {
183
    public Object _persistence_getId() {
197
        return this.primaryKey;
184
        return this.primaryKey;
198
    }
185
    }
199
    @SuppressWarnings("unchecked")
186
    @SuppressWarnings("unchecked")
200
    public void _persistence_setPKVector(Vector pk) {
187
    public void _persistence_setId(Object pk) {
201
        this.primaryKey = pk;
188
        this.primaryKey = pk;
202
    }
189
    }
203
    
190
    
Lines 271-283 Link Here
271
        StringBuilder sb = new StringBuilder(20);
258
        StringBuilder sb = new StringBuilder(20);
272
        sb.append('{');
259
        sb.append('{');
273
        sb.append(getShortClassName(this.getClass()));
260
        sb.append(getShortClassName(this.getClass()));
274
        // use pk vector (directly) to avoid triggering indirection of 'regular' properties
261
        sb.append(this.primaryKey);
275
        if (primaryKey != null && primaryKey.size() > 0) {
276
            for (int i = 0, len = primaryKey.size(); i < len; i++) {
277
                sb.append(' ');
278
                sb.append(primaryKey.elementAt(i));
279
            }
280
        }
281
        sb.append('}');
262
        sb.append('}');
282
        return sb.toString();
263
        return sb.toString();
283
    }
264
    }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/expressions/ObjectExpression.java (-1 / +1 lines)
Lines 98-104 Link Here
98
            List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
98
            List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
99
            for( int i=0; i < childrenTables.size(); i++) {
99
            for( int i=0; i < childrenTables.size(); i++) {
100
                DatabaseTable table = (DatabaseTable)childrenTables.get(i);
100
                DatabaseTable table = (DatabaseTable)childrenTables.get(i);
101
                Expression joinExpression = (Expression)getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
101
                Expression joinExpression = getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
102
                if (getBaseExpression() != null){
102
                if (getBaseExpression() != null){
103
                    joinExpression = getBaseExpression().twist(joinExpression, this);
103
                    joinExpression = getBaseExpression().twist(joinExpression, this);
104
                } else {
104
                } else {
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/expressions/QueryKeyExpression.java (-5 / +5 lines)
Lines 158-177 Link Here
158
        Vector tables = getDescriptor().getTables();
158
        Vector tables = getDescriptor().getTables();
159
        // skip the main table - start with i=1
159
        // skip the main table - start with i=1
160
        int tablesSize = tables.size();
160
        int tablesSize = tables.size();
161
        if(shouldUseOuterJoin()) {
161
        if (shouldUseOuterJoin()) {
162
            for( int i=1; i < tablesSize; i++) {
162
            for (int i=1; i < tablesSize; i++) {
163
                DatabaseTable table = (DatabaseTable)tables.elementAt(i);
163
                DatabaseTable table = (DatabaseTable)tables.elementAt(i);
164
                Expression joinExpression = (Expression)getDescriptor().getQueryManager().getTablesJoinExpressions().get(table);
164
                Expression joinExpression = (Expression)getDescriptor().getQueryManager().getTablesJoinExpressions().get(table);
165
                joinExpression = getBaseExpression().twist(joinExpression, this);
165
                joinExpression = getBaseExpression().twist(joinExpression, this);
166
                tablesJoinExpressions.put(table, joinExpression);
166
                tablesJoinExpressions.put(table, joinExpression);
167
            }
167
            }
168
        }
168
        }
169
        if(isUsingOuterJoinForMultitableInheritance()) {
169
        if (isUsingOuterJoinForMultitableInheritance()) {
170
            List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
170
            List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
171
            tablesSize = childrenTables.size();
171
            tablesSize = childrenTables.size();
172
            for( int i=0; i < tablesSize; i++) {
172
            for (int i=0; i < tablesSize; i++) {
173
                DatabaseTable table = (DatabaseTable)childrenTables.get(i);
173
                DatabaseTable table = (DatabaseTable)childrenTables.get(i);
174
                Expression joinExpression = (Expression)getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
174
                Expression joinExpression = getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
175
                joinExpression = getBaseExpression().twist(joinExpression, this);
175
                joinExpression = getBaseExpression().twist(joinExpression, this);
176
                tablesJoinExpressions.put(table, joinExpression);
176
                tablesJoinExpressions.put(table, joinExpression);
177
            }
177
            }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/expressions/RelationExpression.java (-5 / +1 lines)
Lines 18-24 Link Here
18
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
18
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
19
import org.eclipse.persistence.queries.*;
19
import org.eclipse.persistence.queries.*;
20
import org.eclipse.persistence.internal.helper.*;
20
import org.eclipse.persistence.internal.helper.*;
21
import org.eclipse.persistence.internal.identitymaps.CacheKey;
22
import org.eclipse.persistence.expressions.*;
21
import org.eclipse.persistence.expressions.*;
23
import org.eclipse.persistence.internal.sessions.AbstractRecord;
22
import org.eclipse.persistence.internal.sessions.AbstractRecord;
24
import org.eclipse.persistence.internal.sessions.AbstractSession;
23
import org.eclipse.persistence.internal.sessions.AbstractSession;
Lines 191-201 Link Here
191
        Object leftPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(leftValue, session);
190
        Object leftPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(leftValue, session);
192
        Object rightPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(rightValue, session);
191
        Object rightPrimaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(rightValue, session);
193
192
194
        CacheKey rightCacheKey = new org.eclipse.persistence.internal.identitymaps.CacheKey(rightPrimaryKey);
193
        return performSelector(leftPrimaryKey.equals(rightPrimaryKey));
195
        CacheKey leftCacheKey = new org.eclipse.persistence.internal.identitymaps.CacheKey(leftPrimaryKey);
196
194
197
        return performSelector(rightCacheKey.equals(leftCacheKey));
198
199
    }
195
    }
200
196
201
    /**
197
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/expressions/SQLSelectStatement.java (-1 / +1 lines)
Lines 272-278 Link Here
272
                }
272
                }
273
            } else {
273
            } else {
274
                sourceTable = ((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getTables().firstElement();
274
                sourceTable = ((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getTables().firstElement();
275
                targetTable = (DatabaseTable)((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getInheritancePolicy().getChildrenTables().get(0);
275
                targetTable = ((ClassDescriptor)getDescriptorsForMultitableInheritanceOnly().get(index)).getInheritancePolicy().getChildrenTables().get(0);
276
                Expression exp = (Expression)((Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index)).get(targetTable);
276
                Expression exp = (Expression)((Map)getOuterJoinedAdditionalJoinCriteria().elementAt(index)).get(targetTable);
277
                sourceAlias = exp.aliasForTable(sourceTable);
277
                sourceAlias = exp.aliasForTable(sourceTable);
278
                targetAlias = exp.aliasForTable(targetTable);
278
                targetAlias = exp.aliasForTable(targetTable);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/helper/WriteLockManager.java (-13 / +13 lines)
Lines 265-271 Link Here
265
                for (Map<ObjectChangeSet, ObjectChangeSet> changeSets : changeSet.getObjectChanges().values()) {
265
                for (Map<ObjectChangeSet, ObjectChangeSet> changeSets : changeSet.getObjectChanges().values()) {
266
                    ClassDescriptor descriptor = null;
266
                    ClassDescriptor descriptor = null;
267
                    for (ObjectChangeSet objectChangeSet : changeSets.values()) {
267
                    for (ObjectChangeSet objectChangeSet : changeSets.values()) {
268
                        if (objectChangeSet.getCacheKey() == null) {
268
                        if (objectChangeSet.getId() == null) {
269
                            //skip this process as we will be unable to acquire the correct cachekey anyway
269
                            //skip this process as we will be unable to acquire the correct cachekey anyway
270
                            //this is a new object with identity after write sequencing
270
                            //this is a new object with identity after write sequencing
271
                            continue;
271
                            continue;
Lines 281-305 Link Here
281
                        if (descriptor.shouldIsolateObjectsInUnitOfWork()) {
281
                        if (descriptor.shouldIsolateObjectsInUnitOfWork()) {
282
                            break;
282
                            break;
283
                        }
283
                        }
284
                        CacheKey activeCacheKey = attemptToAcquireLock(descriptor, objectChangeSet.getCacheKey(), session);
284
                        CacheKey activeCacheKey = attemptToAcquireLock(descriptor, objectChangeSet.getId(), session);
285
                        if (activeCacheKey == null) {
285
                        if (activeCacheKey == null) {
286
                            // if cacheKey is null then the lock was not available no need to synchronize this block,because if the
286
                            // if cacheKey is null then the lock was not available no need to synchronize this block,because if the
287
                            // check fails then this thread will just return to the queue until it gets woken up.
287
                            // check fails then this thread will just return to the queue until it gets woken up.
288
                            if (this.prevailingQueue.getFirst() == mergeManager) {
288
                            if (this.prevailingQueue.getFirst() == mergeManager) {
289
                                // wait on this object until it is free,  or until wait time expires because
289
                                // wait on this object until it is free,  or until wait time expires because
290
                                // this thread is the prevailing thread
290
                                // this thread is the prevailing thread
291
                                activeCacheKey = waitOnObjectLock(descriptor, objectChangeSet.getCacheKey(), session, (int)Math.round((Math.random()*500)));
291
                                activeCacheKey = waitOnObjectLock(descriptor, objectChangeSet.getId(), session, (int)Math.round((Math.random()*500)));
292
                            }
292
                            }
293
                            if (activeCacheKey == null) {
293
                            if (activeCacheKey == null) {
294
                                // failed to acquire lock, release all acquired
294
                                // failed to acquire lock, release all acquired
295
                                // locks and place thread on waiting list
295
                                // locks and place thread on waiting list
296
                                releaseAllAcquiredLocks(mergeManager);
296
                                releaseAllAcquiredLocks(mergeManager);
297
                                // get cacheKey
297
                                // get cacheKey
298
                                activeCacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(objectChangeSet.getCacheKey().getKey(), descriptor.getJavaClass(), descriptor);
298
                                activeCacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(objectChangeSet.getId(), descriptor.getJavaClass(), descriptor);
299
                                if (session.shouldLog(SessionLog.FINER, SessionLog.CACHE)) {
299
                                if (session.shouldLog(SessionLog.FINER, SessionLog.CACHE)) {
300
                                    Object[] params = new Object[3];
300
                                    Object[] params = new Object[3];
301
                                    params[0] = descriptor.getJavaClass();
301
                                    params[0] = descriptor.getJavaClass();
302
                                    params[1] = objectChangeSet.getCacheKey() != null ? objectChangeSet.getCacheKey().getKey() : new Vector();
302
                                    params[1] = objectChangeSet.getId();
303
                                    params[2] = Thread.currentThread().getName();
303
                                    params[2] = Thread.currentThread().getName();
304
                                    session.log(SessionLog.FINER, SessionLog.CACHE, "dead_lock_encountered_on_write_no_cachekey", params, null, true);
304
                                    session.log(SessionLog.FINER, SessionLog.CACHE, "dead_lock_encountered_on_write_no_cachekey", params, null, true);
305
                                }
305
                                }
Lines 316-322 Link Here
316
316
317
                                // set the cache key on the merge manager for
317
                                // set the cache key on the merge manager for
318
                                // the object that could not be acquired
318
                                // the object that could not be acquired
319
                                mergeManager.setWriteLockQueued(objectChangeSet.getCacheKey());
319
                                mergeManager.setWriteLockQueued(objectChangeSet.getId());
320
                                try {
320
                                try {
321
                                    if (activeCacheKey != null){
321
                                    if (activeCacheKey != null){
322
                                        //wait on the lock of the object that we couldn't get.
322
                                        //wait on the lock of the object that we couldn't get.
Lines 373-383 Link Here
373
     * a new object that was not locked previously.  Unlike the other methods
373
     * a new object that was not locked previously.  Unlike the other methods
374
     * within this class this method will lock only this object.
374
     * within this class this method will lock only this object.
375
     */
375
     */
376
    public Object appendLock(Vector primaryKeys, Object objectToLock, ClassDescriptor descriptor, MergeManager mergeManager, AbstractSession session) {
376
    public Object appendLock(Object primaryKey, Object objectToLock, ClassDescriptor descriptor, MergeManager mergeManager, AbstractSession session) {
377
        CacheKey lockedCacheKey = session.getIdentityMapAccessorInstance().acquireLockNoWait(primaryKeys, descriptor.getJavaClass(), true, descriptor);
377
        CacheKey lockedCacheKey = session.getIdentityMapAccessorInstance().acquireLockNoWait(primaryKey, descriptor.getJavaClass(), true, descriptor);
378
        if (lockedCacheKey == null) {
378
        if (lockedCacheKey == null) {
379
            session.getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(mergeManager);
379
            session.getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(mergeManager);
380
            lockedCacheKey = session.getIdentityMapAccessorInstance().acquireDeferredLock(primaryKeys, descriptor.getJavaClass(), descriptor);
380
            lockedCacheKey = session.getIdentityMapAccessorInstance().acquireDeferredLock(primaryKey, descriptor.getJavaClass(), descriptor);
381
            Object cachedObject = lockedCacheKey.getObject();
381
            Object cachedObject = lockedCacheKey.getObject();
382
            if (cachedObject == null) {
382
            if (cachedObject == null) {
383
                cachedObject = lockedCacheKey.waitForObject();
383
                cachedObject = lockedCacheKey.waitForObject();
Lines 400-407 Link Here
400
     * This method performs the operations of finding the cacheKey and locking it if possible.
400
     * This method performs the operations of finding the cacheKey and locking it if possible.
401
     * Returns True if the lock was acquired, false otherwise
401
     * Returns True if the lock was acquired, false otherwise
402
     */
402
     */
403
    protected CacheKey attemptToAcquireLock(ClassDescriptor descriptor, CacheKey cacheKey, AbstractSession session) {
403
    protected CacheKey attemptToAcquireLock(ClassDescriptor descriptor, Object primaryKey, AbstractSession session) {
404
        return session.getIdentityMapAccessorInstance().acquireLockNoWait(cacheKey.getKey(), descriptor.getJavaClass(), true, descriptor);
404
        return session.getIdentityMapAccessorInstance().acquireLockNoWait(primaryKey, descriptor.getJavaClass(), true, descriptor);
405
    }
405
    }
406
406
407
    /**
407
    /**
Lines 477-483 Link Here
477
     * This method performs the operations of finding the cacheKey and locking it if possible.
477
     * This method performs the operations of finding the cacheKey and locking it if possible.
478
     * Waits until the lock can be acquired
478
     * Waits until the lock can be acquired
479
     */
479
     */
480
    protected CacheKey waitOnObjectLock(ClassDescriptor descriptor, CacheKey cacheKey, AbstractSession session, int waitTime) {
480
    protected CacheKey waitOnObjectLock(ClassDescriptor descriptor, Object primaryKey, AbstractSession session, int waitTime) {
481
        return session.getIdentityMapAccessorInstance().acquireLockWithWait(cacheKey.getKey(), descriptor.getJavaClass(), true, descriptor, waitTime);
481
        return session.getIdentityMapAccessorInstance().acquireLockWithWait(primaryKey, descriptor.getJavaClass(), true, descriptor, waitTime);
482
    }
482
    }
483
}
483
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/AbstractIdentityMap.java (-50 / +54 lines)
Lines 65-80 Link Here
65
     * Other threads will get deferred locks, all threads will wait until all other threads are complete before releasing their locks.
65
     * Other threads will get deferred locks, all threads will wait until all other threads are complete before releasing their locks.
66
     */
66
     */
67
    public CacheKey acquireDeferredLock(Object primaryKey) {
67
    public CacheKey acquireDeferredLock(Object primaryKey) {
68
        // Create and lock a new cacheKey.
68
        CacheKey cacheKey = getCacheKey(primaryKey);
69
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
70
        newCacheKey.acquireDeferredLock();
71
        // PERF: To avoid synchronization, getIfAbsentPut is used.
72
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
73
        // Return if the newCacheKey was put as it was already locked, otherwise must still lock it.
74
        if (cacheKey == null) {
69
        if (cacheKey == null) {
75
            return newCacheKey;
70
            // Create and lock a new cacheKey.
76
        } else {
71
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
77
            newCacheKey.releaseDeferredLock();
72
            newCacheKey.acquireDeferredLock();
73
            // PERF: To avoid synchronization, getIfAbsentPut is used.
74
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
75
            // Return if the newCacheKey was put as it was already locked, otherwise must still lock it.
76
            if (cacheKey == null) {
77
                return newCacheKey;
78
            } else {
79
                newCacheKey.releaseDeferredLock();
80
            }
78
        }
81
        }
79
        // Acquire a lock on the cache key.
82
        // Acquire a lock on the cache key.
80
        cacheKey.acquireDeferredLock();
83
        cacheKey.acquireDeferredLock();
Lines 86-101 Link Here
86
     * This is used by reading (when using indirection or no relationships) and by merge.
89
     * This is used by reading (when using indirection or no relationships) and by merge.
87
     */
90
     */
88
    public CacheKey acquireLock(Object primaryKey, boolean forMerge) {
91
    public CacheKey acquireLock(Object primaryKey, boolean forMerge) {
89
        // Create and lock a new cacheKey.
92
        CacheKey cacheKey = getCacheKey(primaryKey);
90
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
91
        newCacheKey.acquire(forMerge);
92
        // PERF: To avoid synchronization, getIfAbsentPut is used.
93
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
94
        // Return if the newCacheKey was put as it was already locked, otherwise must still lock it.
95
        if (cacheKey == null) {
93
        if (cacheKey == null) {
96
            return newCacheKey;
94
            // Create and lock a new cacheKey.
97
        } else {
95
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
98
            newCacheKey.release();
96
            newCacheKey.acquire(forMerge);
97
            // PERF: To avoid synchronization, getIfAbsentPut is used.
98
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
99
            // Return if the newCacheKey was put as it was already locked, otherwise must still lock it.
100
            if (cacheKey == null) {
101
                return newCacheKey;
102
            } else {
103
                newCacheKey.release();
104
            }
99
        }
105
        }
100
        // Acquire a lock on the cache key.
106
        // Acquire a lock on the cache key.
101
        cacheKey.acquire();
107
        cacheKey.acquire();
Lines 107-122 Link Here
107
     * This is used by merge for missing existing objects.
113
     * This is used by merge for missing existing objects.
108
     */
114
     */
109
    public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge) {
115
    public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge) {
110
        // Create and lock a new cacheKey.
116
        CacheKey cacheKey = getCacheKey(primaryKey);
111
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
112
        newCacheKey.acquire(forMerge);
113
        // PERF: To avoid synchronization, getIfAbsentPut is used.
114
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
115
        // Return if the newCacheKey was put as already lock, otherwise must still lock.
116
        if (cacheKey == null) {
117
        if (cacheKey == null) {
117
            return newCacheKey;
118
            // Create and lock a new cacheKey.
118
        } else {
119
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
119
            newCacheKey.release();
120
            newCacheKey.acquire(forMerge);
121
            // PERF: To avoid synchronization, getIfAbsentPut is used.
122
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
123
            // Return if the newCacheKey was put as already lock, otherwise must still lock.
124
            if (cacheKey == null) {
125
                return newCacheKey;
126
            } else {
127
                newCacheKey.release();
128
            }
120
        }
129
        }
121
        // Acquire a lock on the cache key.
130
        // Acquire a lock on the cache key.
122
        // Return null if already locked.
131
        // Return null if already locked.
Lines 131-146 Link Here
131
     * This is used by merge for missing existing objects.
140
     * This is used by merge for missing existing objects.
132
     */
141
     */
133
    public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) {
142
    public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) {
134
        // Create and lock a new cacheKey.
143
        CacheKey cacheKey = getCacheKey(primaryKey);
135
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
136
        newCacheKey.acquire(forMerge);
137
        // PERF: To avoid synchronization, getIfAbsentPut is used.
138
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
139
        // Return if the newCacheKey was put as already lock, otherwise must still lock.
140
        if (cacheKey == null) {
144
        if (cacheKey == null) {
141
            return newCacheKey;
145
            // Create and lock a new cacheKey.
142
        } else {
146
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
143
            newCacheKey.release();
147
            newCacheKey.acquire(forMerge);
148
            // PERF: To avoid synchronization, getIfAbsentPut is used.
149
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
150
            // Return if the newCacheKey was put as already lock, otherwise must still lock.
151
            if (cacheKey == null) {
152
                return newCacheKey;
153
            } else {
154
                newCacheKey.release();
155
            }
144
        }
156
        }
145
        // Acquire a lock on the cache key.
157
        // Acquire a lock on the cache key.
146
        // Return null if already locked.
158
        // Return null if already locked.
Lines 156-164 Link Here
156
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
168
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
157
     */
169
     */
158
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey) {
170
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey) {
159
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
171
        CacheKey cacheKey = getCacheKey(primaryKey);
160
        CacheKey cacheKey = getCacheKey(newCacheKey);
161
        if (cacheKey == null) {
172
        if (cacheKey == null) {
173
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
162
            // Lock new cacheKey.
174
            // Lock new cacheKey.
163
            newCacheKey.acquireReadLock();
175
            newCacheKey.acquireReadLock();
164
            // Create one but not put it in the cache, as we are only reading
176
            // Create one but not put it in the cache, as we are only reading
Lines 177-185 Link Here
177
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
189
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
178
     */
190
     */
179
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey) {
191
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey) {
180
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
192
        CacheKey cacheKey = getCacheKey(primaryKey);
181
        CacheKey cacheKey = getCacheKey(newCacheKey);
182
        if (cacheKey == null) {
193
        if (cacheKey == null) {
194
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
183
            // Lock new cacheKey.
195
            // Lock new cacheKey.
184
            newCacheKey.acquireReadLock();
196
            newCacheKey.acquireReadLock();
185
            // Create one but not put it in the cache, as we are only reading
197
            // Create one but not put it in the cache, as we are only reading
Lines 255-264 Link Here
255
    /**
267
    /**
256
     * Get the cache key (with object) for the primary key.
268
     * Get the cache key (with object) for the primary key.
257
     */
269
     */
258
    public CacheKey getCacheKey(Object primaryKey) {
270
    public abstract CacheKey getCacheKey(Object primaryKey);
259
        CacheKey searchKey = new CacheKey(primaryKey);
260
        return getCacheKey(searchKey);
261
    }
262
271
263
    /**
272
    /**
264
     * Get the cache key (with object) for the primary key.
273
     * Get the cache key (with object) for the primary key.
Lines 266-283 Link Here
266
    public CacheKey getCacheKeyForLock(Object primaryKey) {
275
    public CacheKey getCacheKeyForLock(Object primaryKey) {
267
        return getCacheKey(primaryKey);
276
        return getCacheKey(primaryKey);
268
    }
277
    }
269
270
    /**
271
     * Return the cache key (with object) matching the searchKey.
272
     */
273
    protected abstract CacheKey getCacheKey(CacheKey searchKey);
274
    
278
    
275
    /**
279
    /**
276
     * Return the CacheKey (with object) matching the searchKey.
280
     * Return the CacheKey (with object) matching the searchKey.
277
     * If the CacheKey is missing then put the searchKey in the map.
281
     * If the CacheKey is missing then put the searchKey in the map.
278
     * The searchKey should have already been locked. 
282
     * The searchKey should have already been locked. 
279
     */
283
     */
280
    protected abstract CacheKey getCacheKeyIfAbsentPut(CacheKey cacheKey);
284
    protected abstract CacheKey putCacheKeyIfAbsent(CacheKey cacheKey);
281
285
282
    /**
286
    /**
283
     * Get the cache key (with object) for the primary key with read lock.
287
     * Get the cache key (with object) for the primary key with read lock.
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/CacheId.java (+177 lines)
Line 0 Link Here
1
/*******************************************************************************
2
 * Copyright (c) 1998, 2010 Oracle. All rights reserved.
3
 * This program and the accompanying materials are made available under the 
4
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
5
 * which accompanies this distribution. 
6
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
7
 * and the Eclipse Distribution License is available at 
8
 * http://www.eclipse.org/org/documents/edl-v10.php.
9
 *
10
 * Contributors:
11
 *     James Sutherland - initial API and implementation
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.identitymaps;
14
15
import java.io.*;
16
import java.util.Arrays;
17
18
import org.eclipse.persistence.internal.helper.*;
19
20
/**
21
 * Defines a wrapper for a primary key (Id) to use as a key in the cache.
22
 * 
23
 * @since EclipseLink 2.1
24
 * @author James Sutherland
25
 */
26
public class CacheId implements Serializable {
27
28
    /** The primary key values. */
29
    protected Object[] primaryKey;
30
31
    /** Cached hashcode. */
32
    protected int hash;
33
    
34
    public CacheId(Object[] primaryKey) {
35
        this.primaryKey = primaryKey;
36
        this.hash = computeHash(primaryKey);
37
    }
38
39
    public Object[] getPrimaryKey() {
40
        return primaryKey;
41
    }
42
43
    public void setPrimaryKey(Object[] primaryKey) {
44
        this.primaryKey = primaryKey;
45
        this.hash = computeHash(primaryKey);
46
    }
47
    
48
    /**
49
     * Append the value to the end of the primary key values.
50
     */
51
    public void add(Object value) {
52
        Object[] array = new Object[this.primaryKey.length + 1];
53
        System.arraycopy(this.primaryKey, 0, array, 0, this.primaryKey.length);
54
        array[this.primaryKey.length] = value;
55
        setPrimaryKey(array);
56
    }
57
    
58
    /**
59
     * Set the value in the primary key values.
60
     */
61
    public void set(int index, Object value) {
62
        this.primaryKey[index] = value;
63
        setPrimaryKey(this.primaryKey);
64
    }
65
    
66
    /**
67
     * Pre-compute the hash to optimize hash calls.
68
     */
69
    protected int computeHash(Object[] primaryKey) {
70
        int hashValue = 0;
71
        for (Object value : primaryKey) {
72
            if (value != null) {
73
            	//bug5709489, gf bug 1193: fix to handle array hashcodes properly
74
            	if (value.getClass().isArray()) {
75
            	    hashValue = hashValue ^ computeArrayHashCode(value);
76
            	} else {
77
            	    hashValue = hashValue ^ value.hashCode();
78
            	}
79
            }
80
        }
81
        return hashValue;
82
    }
83
84
    /**
85
     * Compute the hashcode for supported array types.
86
     */
87
    private int computeArrayHashCode(Object obj) {
88
        if (obj.getClass() == ClassConstants.APBYTE) {
89
            return Arrays.hashCode((byte[]) obj);
90
        } else if (obj.getClass() == ClassConstants.APCHAR) {
91
            return Arrays.hashCode((char[]) obj);
92
        } else {
93
            return Arrays.hashCode((Object[]) obj);
94
        }
95
    }
96
97
    /**
98
     * Return the precomputed hashcode.
99
     */
100
    @Override
101
    public int hashCode() {
102
        return this.hash;
103
    }
104
    
105
    /**
106
     * Determine if the receiver is equal to anObject.
107
     * If anObject is a CacheKey, do further comparison, otherwise, return false.
108
     * @see CacheKey#equals(CacheKey)
109
     */
110
    @Override
111
    public boolean equals(Object object) {
112
        try {
113
            return equals((CacheId)object);
114
        } catch (ClassCastException incorrectType) {
115
            return false;
116
        }
117
    }
118
119
    /**
120
     * Determine if the receiver is equal to key.
121
     * Use an index compare, because it is much faster than enumerations.
122
     */
123
    public boolean equals(CacheId id) {
124
        if (this == id) {
125
            return true;
126
        }
127
        if (this.hash != id.hash) {
128
            return false;
129
        }
130
        // PERF: Using direct variable access.
131
        int size = this.primaryKey.length;
132
        Object[] otherKey = id.primaryKey;
133
        if (size == otherKey.length) {
134
            for (int index = 0; index < size; index++) {
135
                Object value = this.primaryKey[index];
136
                Object otherValue = otherKey[index];
137
                if (value == null) {
138
                    if (otherValue != null) {
139
                        return false;
140
                    } else {
141
                        continue;
142
                    }
143
                } else if (otherValue == null) {
144
                    return false;
145
                }
146
                Class valueClass = value.getClass();
147
                Class otherClass = otherValue.getClass();
148
                if (valueClass.isArray()) {
149
                    //gf bug 1193: fix array comparison logic to exit if they don't match, and continue the loop if they do
150
                    if (((valueClass == ClassConstants.APBYTE) && (otherClass == ClassConstants.APBYTE)) ) {
151
                        if (!Helper.compareByteArrays((byte[])value, (byte[])otherValue)){
152
                            return false;
153
                        }
154
                    } else if (((valueClass == ClassConstants.APCHAR) && (otherClass == ClassConstants.APCHAR)) ) {
155
                        if (!Helper.compareCharArrays((char[])value, (char[])otherValue)){
156
                            return false;
157
                        }
158
                    } else {
159
                        if (!Helper.compareArrays((Object[])value, (Object[])otherValue)) {
160
                            return false;
161
                        }
162
                    }
163
                } else {
164
                    if (!(value.equals(otherValue))) {
165
                        return false;
166
                    }
167
                }
168
            }
169
            return true;
170
        }
171
        return false;
172
    }
173
174
    public String toString() {
175
        return "[" + Arrays.asList(this.primaryKey) + ": " + this.hash + "]";
176
    }
177
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/CacheIdentityMap.java (-11 / +9 lines)
Lines 12-29 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.identitymaps;
13
package org.eclipse.persistence.internal.identitymaps;
14
14
15
import java.util.*;
16
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
16
19
/**
17
/**
20
 * <p><b>Purpose</b>: A fixed size LRU cache<p>
18
 * <p><b>Purpose</b>: A fixed size LRU cache<p>
21
 * Using a linked list as well as the hashtable from the superclass a LRU cache is maintained.
19
 * Using a linked list as well as the map from the superclass a LRU cache is maintained.
22
 * When a get is executed the LRU list is updated and when a new object is inserted the object
20
 * When a get is executed the LRU list is updated and when a new object is inserted the object
23
 * at the start of the list is deleted (provided the maxSize has been reached).
21
 * at the start of the list is deleted (provided the maxSize has been reached).
24
 * <p><b>Responsibilities</b>:<ul>
22
 * <p><b>Responsibilities</b>:<ul>
25
 *    <li> Guarantees identity through primary key values
23
 *    <li> Guarantees identity through primary key values
26
 * <li> Keeps the LRU linked list updated.
24
 *    <li> Keeps the LRU linked list updated.
27
 * </ul>
25
 * </ul>
28
 * @since TOPLink/Java 1.0
26
 * @since TOPLink/Java 1.0
29
 */
27
 */
Lines 41-63 Link Here
41
     */
39
     */
42
    public CacheIdentityMap(int size) {
40
    public CacheIdentityMap(int size) {
43
        super(size);
41
        super(size);
44
        this.first = new LinkedCacheKey(new Vector(0), null, null, 0);
42
        this.first = new LinkedCacheKey(new CacheId(new Object[0]), null, null, 0);
45
        this.last = new LinkedCacheKey(new Vector(0), null, null, 0);
43
        this.last = new LinkedCacheKey(new CacheId(new Object[0]), null, null, 0);
46
        this.first.setNext(this.last);
44
        this.first.setNext(this.last);
47
        this.last.setPrevious(this.first);
45
        this.last.setPrevious(this.first);
48
    };
46
    };
49
47
50
    public CacheIdentityMap(int size, ClassDescriptor descriptor) {
48
    public CacheIdentityMap(int size, ClassDescriptor descriptor) {
51
        super(size, descriptor);
49
        super(size, descriptor);
52
        this.first = new LinkedCacheKey(new Vector(0), null, null, 0);
50
        this.first = new LinkedCacheKey(new CacheId(new Object[0]), null, null, 0);
53
        this.last = new LinkedCacheKey(new Vector(0), null, null, 0);
51
        this.last = new LinkedCacheKey(new CacheId(new Object[0]), null, null, 0);
54
        this.first.setNext(this.last);
52
        this.first.setNext(this.last);
55
        this.last.setPrevious(this.first);
53
        this.last.setPrevious(this.first);
56
    }
54
    }
57
55
58
    @Override
56
    @Override
59
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
57
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
60
        return new LinkedCacheKey((Vector)primaryKey, object, writeLockValue, readTime);
58
        return new LinkedCacheKey(primaryKey, object, writeLockValue, readTime);
61
    }
59
    }
62
60
63
    /**
61
    /**
Lines 114-121 Link Here
114
    /**
112
    /**
115
     * Also insert the link if the cacheKey is put.
113
     * Also insert the link if the cacheKey is put.
116
     */
114
     */
117
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey searchKey) {
115
    protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) {
118
        CacheKey cacheKey = super.getCacheKeyIfAbsentPut(searchKey);
116
        CacheKey cacheKey = super.putCacheKeyIfAbsent(searchKey);
119
        if (cacheKey == null) {
117
        if (cacheKey == null) {
120
            insertLink((LinkedCacheKey)searchKey);
118
            insertLink((LinkedCacheKey)searchKey);
121
            ensureFixedSize();
119
            ensureFixedSize();
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/CacheKey.java (-87 / +8 lines)
Lines 13-20 Link Here
13
package org.eclipse.persistence.internal.identitymaps;
13
package org.eclipse.persistence.internal.identitymaps;
14
14
15
import java.io.*;
15
import java.io.*;
16
import java.util.Arrays;
17
import java.util.Vector;
18
16
19
import org.eclipse.persistence.exceptions.ConcurrencyException;
17
import org.eclipse.persistence.exceptions.ConcurrencyException;
20
import org.eclipse.persistence.internal.helper.*;
18
import org.eclipse.persistence.internal.helper.*;
Lines 31-40 Link Here
31
public class CacheKey implements Serializable, Cloneable {
29
public class CacheKey implements Serializable, Cloneable {
32
30
33
    /** The key holds the vector of primary key values for the object. */
31
    /** The key holds the vector of primary key values for the object. */
34
    protected Vector key;
32
    protected Object key;
35
33
36
    /** Calculated hash value for CacheKey from primary key values. */
37
    protected int hash;
38
    protected Object object;
34
    protected Object object;
39
    
35
    
40
    //used to store a reference to the map this cachekey is in in cases where the
36
    //used to store a reference to the map this cachekey is in in cases where the
Lines 88-100 Link Here
88
    }
84
    }
89
    
85
    
90
    public CacheKey(Object primaryKey) {
86
    public CacheKey(Object primaryKey) {
91
        this.key = (Vector)primaryKey;
87
        this.key = primaryKey;
92
        this.hash = computeHash((Vector)primaryKey);
93
    }
88
    }
94
89
95
    public CacheKey(Object primaryKey, Object object, Object lockValue) {
90
    public CacheKey(Object primaryKey, Object object, Object lockValue) {
96
        this.key = (Vector)primaryKey;
91
        this.key = primaryKey;
97
        this.hash = computeHash((Vector)primaryKey);
98
        this.writeLockValue = lockValue;
92
        this.writeLockValue = lockValue;
99
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
93
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
100
        if (object != null) {
94
        if (object != null) {
Lines 103-110 Link Here
103
    }
97
    }
104
98
105
    public CacheKey(Object primaryKey, Object object, Object lockValue, long readTime) {
99
    public CacheKey(Object primaryKey, Object object, Object lockValue, long readTime) {
106
        this.key = (Vector)primaryKey;
100
        this.key = primaryKey;
107
        this.hash = computeHash((Vector)primaryKey);
108
        this.writeLockValue = lockValue;
101
        this.writeLockValue = lockValue;
109
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
102
        //bug4649617  use setter instead of this.object = object to avoid hard reference on object in subclasses
110
        if (object != null) {
103
        if (object != null) {
Lines 220-262 Link Here
220
    }
213
    }
221
214
222
    /**
215
    /**
223
     * Compute a hash value for the CacheKey dependent upon the values of the primary key
224
     * instead of the identity of the receiver.
225
     * This method is intended for use by constructors only.
226
     */
227
    protected int computeHash(Vector primaryKey) {
228
        int computedHashValue = 0;
229
        int size = primaryKey.size();
230
        for (int index = 0; index < size; index++) {
231
            Object value = primaryKey.get(index);
232
            if (value != null) {
233
            	//bug5709489, gf bug 1193: fix to handle array hashcodes properly
234
            	if (value.getClass().isArray()) {
235
            		computedHashValue = computedHashValue ^ computeArrayHashCode(value);
236
            	} else {
237
            		computedHashValue = computedHashValue ^ (value.hashCode());
238
            	}
239
            }
240
        }
241
        return computedHashValue;
242
    }
243
244
    /**
245
     * Compute the hashcode for supported array types
246
     * @param obj - an array
247
     * @return hashCode value
248
     */
249
    private int computeArrayHashCode(Object obj) {
250
        if (obj.getClass() == ClassConstants.APBYTE) {
251
            return Arrays.hashCode((byte []) obj);
252
        } else if (obj.getClass() == ClassConstants.APCHAR) {
253
            return Arrays.hashCode((char []) obj);
254
        } else {
255
            return Arrays.hashCode((Object []) obj);
256
        }
257
    }
258
259
    /**
260
     * Determine if the receiver is equal to anObject.
216
     * Determine if the receiver is equal to anObject.
261
     * If anObject is a CacheKey, do further comparison, otherwise, return false.
217
     * If anObject is a CacheKey, do further comparison, otherwise, return false.
262
     * @see CacheKey#equals(CacheKey)
218
     * @see CacheKey#equals(CacheKey)
Lines 277-317 Link Here
277
        if (this == key) {
233
        if (this == key) {
278
            return true;
234
            return true;
279
        }
235
        }
280
        // PERF: Using direct variable access.
236
        return this.key.equals(key.key);
281
        int size = this.key.size();
282
        if (size == key.key.size()) {
283
            for (int index = 0; index < size; index++) {
284
                Object myValue = this.key.get(index);
285
                Object comparisionValue = key.key.get(index);
286
287
                if (myValue == null) {
288
                    if (comparisionValue != null) {
289
                        return false;
290
                    }
291
                } else if (myValue.getClass().isArray()) {
292
                    //gf bug 1193: fix array comparison logic to exit if they don't match, and continue the loop if they do
293
                    if (((myValue.getClass() == ClassConstants.APBYTE) && (comparisionValue.getClass() == ClassConstants.APBYTE)) ) {
294
                        if (!Helper.compareByteArrays((byte[])myValue, (byte[])comparisionValue)){
295
                            return false;
296
                        }
297
                    } else if (((myValue.getClass() == ClassConstants.APCHAR) && (comparisionValue.getClass() == ClassConstants.APCHAR)) ) {
298
                        if (!Helper.compareCharArrays((char[])myValue, (char[])comparisionValue)){
299
                            return false;
300
                        }
301
                    } else {
302
                        if (!Helper.compareArrays((Object[])myValue, (Object[])comparisionValue)) {
303
                            return false;
304
                        }
305
                    }
306
                } else {
307
                    if (!(myValue.equals(comparisionValue))) {
308
                        return false;
309
                    }
310
                }
311
            }
312
            return true;
313
        }
314
        return false;
315
    }
237
    }
316
238
317
    /**
239
    /**
Lines 325-331 Link Here
325
        return this.lastUpdatedQueryId;
247
        return this.lastUpdatedQueryId;
326
    }
248
    }
327
249
328
    public Vector getKey() {
250
    public Object getKey() {
329
        return key;
251
        return key;
330
    }
252
    }
331
253
Lines 383-389 Link Here
383
     * Overrides hashCode() in Object to use the primaryKey's hashCode for storage in data structures.
305
     * Overrides hashCode() in Object to use the primaryKey's hashCode for storage in data structures.
384
     */
306
     */
385
    public int hashCode() {
307
    public int hashCode() {
386
        return hash;
308
        return this.key.hashCode();
387
    }
309
    }
388
310
389
    /**
311
    /**
Lines 465-473 Link Here
465
        this.lastUpdatedQueryId = id;
387
        this.lastUpdatedQueryId = id;
466
    }
388
    }
467
389
468
    public void setKey(Vector key) {
390
    public void setKey(Object key) {
469
        this.key = key;
391
        this.key = key;
470
        this.hash = computeHash(key);
471
    }
392
    }
472
393
473
    /**
394
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/FullIdentityMap.java (-20 / +15 lines)
Lines 28-34 Link Here
28
public class FullIdentityMap extends AbstractIdentityMap {
28
public class FullIdentityMap extends AbstractIdentityMap {
29
29
30
    /** Map of CacheKeys stored using their key. */
30
    /** Map of CacheKeys stored using their key. */
31
    protected Map<CacheKey, CacheKey> cacheKeys;
31
    protected Map<Object, CacheKey> cacheKeys;
32
32
33
    public FullIdentityMap() {}
33
    public FullIdentityMap() {}
34
    
34
    
Lines 49-59 Link Here
49
    @Override
49
    @Override
50
    public Object clone() {
50
    public Object clone() {
51
        FullIdentityMap clone = (FullIdentityMap)super.clone();
51
        FullIdentityMap clone = (FullIdentityMap)super.clone();
52
        clone.setCacheKeys(new ConcurrentHashMap(getCacheKeys().size()));
52
        clone.setCacheKeys(new ConcurrentHashMap(this.cacheKeys.size()));
53
53
54
        for (Iterator cacheKeysIterator = getCacheKeys().values().iterator(); cacheKeysIterator.hasNext();) {
54
        for (Iterator cacheKeysIterator = this.cacheKeys.values().iterator(); cacheKeysIterator.hasNext();) {
55
            CacheKey key = (CacheKey)((CacheKey)cacheKeysIterator.next()).clone();
55
            CacheKey key = (CacheKey)((CacheKey)cacheKeysIterator.next()).clone();
56
            clone.getCacheKeys().put(key, key);
56
            clone.getCacheKeys().put(key.getKey(), key);
57
        }
57
        }
58
58
59
        return clone;
59
        return clone;
Lines 65-71 Link Here
65
     */
65
     */
66
    @Override
66
    @Override
67
    public void collectLocks(HashMap threadList) {
67
    public void collectLocks(HashMap threadList) {
68
        Iterator cacheKeyIterator = getCacheKeys().values().iterator();
68
        Iterator cacheKeyIterator = this.cacheKeys.values().iterator();
69
        while (cacheKeyIterator.hasNext()) {
69
        while (cacheKeyIterator.hasNext()) {
70
            CacheKey cacheKey = (CacheKey)cacheKeyIterator.next();
70
            CacheKey cacheKey = (CacheKey)cacheKeyIterator.next();
71
            if (cacheKey.isAcquired()) {
71
            if (cacheKey.isAcquired()) {
Lines 93-100 Link Here
93
     * If no object for the key exists, return null.
93
     * If no object for the key exists, return null.
94
     */
94
     */
95
    @Override
95
    @Override
96
    protected CacheKey getCacheKey(CacheKey searchKey) {
96
    public CacheKey getCacheKey(Object searchKey) {
97
        return getCacheKeys().get(searchKey);
97
        return this.cacheKeys.get(searchKey);
98
    }    
98
    }    
99
        
99
        
100
    /**
100
    /**
Lines 103-122 Link Here
103
     * The searchKey should have already been locked. 
103
     * The searchKey should have already been locked. 
104
     */
104
     */
105
    @Override
105
    @Override
106
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey searchKey) {
106
    protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) {
107
        // PERF: First to a get, and get is non-locking, putIfAbsent locks.
107
        searchKey.setOwningMap(this);
108
        CacheKey cacheKey = getCacheKeys().get(searchKey);
108
        return (CacheKey)((ConcurrentMap)this.cacheKeys).putIfAbsent(searchKey.getKey(), searchKey);
109
        if (cacheKey == null) {
110
            searchKey.setOwningMap(this);
111
            cacheKey = (CacheKey)((ConcurrentMap)getCacheKeys()).putIfAbsent(searchKey, searchKey);
112
        }
113
        return cacheKey;
114
    }
109
    }
115
110
116
    /**
111
    /**
117
     * Return the cache keys.
112
     * Return the cache keys.
118
     */
113
     */
119
    public Map<CacheKey, CacheKey> getCacheKeys() {
114
    public Map<Object, CacheKey> getCacheKeys() {
120
        return cacheKeys;
115
        return cacheKeys;
121
    }
116
    }
122
117
Lines 136-142 Link Here
136
    @Override
131
    @Override
137
    public int getSize(Class myClass, boolean recurse) {
132
    public int getSize(Class myClass, boolean recurse) {
138
        int count = 0;
133
        int count = 0;
139
        Iterator keys = getCacheKeys().values().iterator();
134
        Iterator keys = this.cacheKeys.values().iterator();
140
135
141
        while (keys.hasNext()) {
136
        while (keys.hasNext()) {
142
            CacheKey key = (CacheKey)keys.next();
137
            CacheKey key = (CacheKey)keys.next();
Lines 184-190 Link Here
184
    public CacheKey put(Object primaryKey, Object object, Object writeLockValue, long readTime) {
179
    public CacheKey put(Object primaryKey, Object object, Object writeLockValue, long readTime) {
185
        CacheKey newCacheKey = createCacheKey(primaryKey, object, writeLockValue, readTime);
180
        CacheKey newCacheKey = createCacheKey(primaryKey, object, writeLockValue, readTime);
186
        // Find the cache key in the map, reset it, or put the new one.
181
        // Find the cache key in the map, reset it, or put the new one.
187
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
182
        CacheKey cacheKey = putCacheKeyIfAbsent(newCacheKey);
188
        if (cacheKey != null) {
183
        if (cacheKey != null) {
189
            // The cache key is locked inside resetCacheKey() to keep other threads from accessing the object.
184
            // The cache key is locked inside resetCacheKey() to keep other threads from accessing the object.
190
            resetCacheKey(cacheKey, object, writeLockValue, readTime);
185
            resetCacheKey(cacheKey, object, writeLockValue, readTime);
Lines 204-210 Link Here
204
        if (cacheKey != null) {
199
        if (cacheKey != null) {
205
            // Cache key needs to be locked when removing from the map.
200
            // Cache key needs to be locked when removing from the map.
206
            cacheKey.acquire();
201
            cacheKey.acquire();
207
            getCacheKeys().remove(cacheKey);
202
            this.cacheKeys.remove(cacheKey.getKey());
208
            // Cache key needs to be released after removing from the map.
203
            // Cache key needs to be released after removing from the map.
209
            cacheKey.release();
204
            cacheKey.release();
210
            return cacheKey.getObject();
205
            return cacheKey.getObject();
Lines 224-230 Link Here
224
        key.release();
219
        key.release();
225
    }
220
    }
226
221
227
    protected void setCacheKeys(Map<CacheKey, CacheKey> cacheKeys) {
222
    protected void setCacheKeys(Map<Object, CacheKey> cacheKeys) {
228
        this.cacheKeys = cacheKeys;
223
        this.cacheKeys = cacheKeys;
229
    }
224
    }
230
}
225
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/HardCacheWeakIdentityMap.java (-4 / +2 lines)
Lines 12-19 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.identitymaps;
13
package org.eclipse.persistence.internal.identitymaps;
14
14
15
import java.util.*;
16
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.internal.helper.linkedlist.*;
16
import org.eclipse.persistence.internal.helper.linkedlist.*;
19
17
Lines 46-52 Link Here
46
     */
44
     */
47
    @Override
45
    @Override
48
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
46
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
49
        return new ReferenceCacheKey((Vector)primaryKey, object, writeLockValue, readTime);
47
        return new ReferenceCacheKey(primaryKey, object, writeLockValue, readTime);
50
    }
48
    }
51
49
52
    /**
50
    /**
Lines 119-125 Link Here
119
    public class ReferenceCacheKey extends WeakCacheKey {
117
    public class ReferenceCacheKey extends WeakCacheKey {
120
        protected LinkedNode referenceNode;
118
        protected LinkedNode referenceNode;
121
119
122
        public ReferenceCacheKey(Vector primaryKey, Object object, Object writeLockValue, long readTime) {
120
        public ReferenceCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
123
            super(primaryKey, object, writeLockValue, readTime);
121
            super(primaryKey, object, writeLockValue, readTime);
124
        }
122
        }
125
123
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/IdentityMapManager.java (-12 / +58 lines)
Lines 114-119 Link Here
114
     * called with true from the merge process, if true then the refresh will not refresh the object.
114
     * called with true from the merge process, if true then the refresh will not refresh the object.
115
     */
115
     */
116
    public CacheKey acquireLock(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
116
    public CacheKey acquireLock(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
117
        if (primaryKey == null) {
118
            CacheKey cacheKey = new CacheKey(primaryKey);
119
            cacheKey.acquire();
120
            return cacheKey;
121
        }
117
        CacheKey cacheKey = null;
122
        CacheKey cacheKey = null;
118
        if (this.isCacheAccessPreCheckRequired) {
123
        if (this.isCacheAccessPreCheckRequired) {
119
            this.session.startOperationProfile(SessionProfiler.CACHE);
124
            this.session.startOperationProfile(SessionProfiler.CACHE);
Lines 136-141 Link Here
136
     * called with true from the merge process, if true then the refresh will not refresh the object.
141
     * called with true from the merge process, if true then the refresh will not refresh the object.
137
     */
142
     */
138
    public CacheKey acquireLockNoWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
143
    public CacheKey acquireLockNoWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
144
        if (primaryKey == null) {
145
            CacheKey cacheKey = new CacheKey(primaryKey);
146
            cacheKey.acquire();
147
            return cacheKey;
148
        }
139
        CacheKey cacheKey = null;
149
        CacheKey cacheKey = null;
140
        if (this.isCacheAccessPreCheckRequired) {
150
        if (this.isCacheAccessPreCheckRequired) {
141
            this.session.startOperationProfile(SessionProfiler.CACHE);
151
            this.session.startOperationProfile(SessionProfiler.CACHE);
Lines 158-163 Link Here
158
     * called with true from the merge process, if true then the refresh will not refresh the object.
168
     * called with true from the merge process, if true then the refresh will not refresh the object.
159
     */
169
     */
160
    public CacheKey acquireLockWithWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, int wait) {
170
    public CacheKey acquireLockWithWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, int wait) {
171
        if (primaryKey == null) {
172
            CacheKey cacheKey = new CacheKey(primaryKey);
173
            cacheKey.acquire();
174
            return cacheKey;
175
        }
161
        CacheKey cacheKey = null;
176
        CacheKey cacheKey = null;
162
        if (this.isCacheAccessPreCheckRequired) {
177
        if (this.isCacheAccessPreCheckRequired) {
163
            this.session.startOperationProfile(SessionProfiler.CACHE);
178
            this.session.startOperationProfile(SessionProfiler.CACHE);
Lines 208-213 Link Here
208
     * the object while the read lock is held.
223
     * the object while the read lock is held.
209
     */
224
     */
210
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
225
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
226
        if (primaryKey == null) {
227
            CacheKey cacheKey = new CacheKey(primaryKey);
228
            cacheKey.acquireReadLock();
229
            return cacheKey;
230
        }
211
        CacheKey cacheKey = null;
231
        CacheKey cacheKey = null;
212
        if (this.isCacheAccessPreCheckRequired) {
232
        if (this.isCacheAccessPreCheckRequired) {
213
            this.session.startOperationProfile(SessionProfiler.CACHE);
233
            this.session.startOperationProfile(SessionProfiler.CACHE);
Lines 233-238 Link Here
233
     * If no readlock can be acquired then do not wait but return null.
253
     * If no readlock can be acquired then do not wait but return null.
234
     */
254
     */
235
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
255
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
256
        if (primaryKey == null) {
257
            CacheKey cacheKey = new CacheKey(primaryKey);
258
            cacheKey.acquireReadLock();
259
            return cacheKey;
260
        }
236
        CacheKey cacheKey = null;
261
        CacheKey cacheKey = null;
237
        if (this.isCacheAccessPreCheckRequired) {
262
        if (this.isCacheAccessPreCheckRequired) {
238
            this.session.startOperationProfile(SessionProfiler.CACHE);
263
            this.session.startOperationProfile(SessionProfiler.CACHE);
Lines 574-579 Link Here
574
     * Retrieve the cache key for the given identity information.
599
     * Retrieve the cache key for the given identity information.
575
     */
600
     */
576
    public CacheKey getCacheKeyForObjectForLock(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
601
    public CacheKey getCacheKeyForObjectForLock(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
602
        if (primaryKey == null) {
603
            return null;
604
        }
577
        IdentityMap map = getIdentityMap(descriptor, true);
605
        IdentityMap map = getIdentityMap(descriptor, true);
578
        if (map == null) {
606
        if (map == null) {
579
            return null;
607
            return null;
Lines 598-603 Link Here
598
     * Retrieve the cache key for the given identity information.
626
     * Retrieve the cache key for the given identity information.
599
     */
627
     */
600
    public CacheKey getCacheKeyForObject(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
628
    public CacheKey getCacheKeyForObject(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
629
        if (primaryKey == null) {
630
            return null;
631
        }
601
        IdentityMap map = getIdentityMap(descriptor, true);
632
        IdentityMap map = getIdentityMap(descriptor, true);
602
        if (map == null) {
633
        if (map == null) {
603
            return null;
634
            return null;
Lines 910-918 Link Here
910
            return null;
941
            return null;
911
        }
942
        }
912
943
913
        Object lookupParameters = parameters;
944
        Object lookupParameters;
914
        if (lookupParameters == null) {
945
        if (parameters == null) {
915
            lookupParameters = new NonSynchronizedVector(0);
946
            lookupParameters = new CacheId(new Object[0]);
947
        } else {
948
            lookupParameters = new CacheId(parameters.toArray());
916
        }
949
        }
917
950
918
        CacheKey key = map.getCacheKey(lookupParameters);
951
        CacheKey key = map.getCacheKey(lookupParameters);
Lines 967-972 Link Here
967
     * Retrieve the write lock value of the cache key associated with the given primary key,
1000
     * Retrieve the write lock value of the cache key associated with the given primary key,
968
     */
1001
     */
969
    public Object getWriteLockValue(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
1002
    public Object getWriteLockValue(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
1003
        if (primaryKey == null) {
1004
            return null;
1005
        }
970
        IdentityMap map = getIdentityMap(descriptor, false);
1006
        IdentityMap map = getIdentityMap(descriptor, false);
971
        Object value;
1007
        Object value;
972
        if (this.isCacheAccessPreCheckRequired) {
1008
        if (this.isCacheAccessPreCheckRequired) {
Lines 1028-1040 Link Here
1028
        if (descriptor.hasInheritance()) {
1064
        if (descriptor.hasInheritance()) {
1029
            if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
1065
            if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
1030
                writer.write(LoggingLocalization.buildMessage("includes"));
1066
                writer.write(LoggingLocalization.buildMessage("includes"));
1031
                Vector childDescriptors;
1067
                List<ClassDescriptor> childDescriptors = descriptor.getInheritancePolicy().getChildDescriptors();
1032
                childDescriptors = descriptor.getInheritancePolicy().getChildDescriptors();
1033
                if ((childDescriptors != null) && (childDescriptors.size() != 0)) {//Bug#2675242
1068
                if ((childDescriptors != null) && (childDescriptors.size() != 0)) {//Bug#2675242
1034
                    Enumeration enum2 = childDescriptors.elements();
1069
                    Iterator<ClassDescriptor> iterator = childDescriptors.iterator();
1035
                    writer.write(Helper.getShortClassName(((ClassDescriptor)enum2.nextElement()).getJavaClass()));
1070
                    writer.write(Helper.getShortClassName(iterator.next().getJavaClass()));
1036
                    while (enum2.hasMoreElements()) {
1071
                    while (iterator.hasNext()) {
1037
                        writer.write(", " + Helper.getShortClassName(((ClassDescriptor)enum2.nextElement()).getJavaClass()));
1072
                        writer.write(", " + Helper.getShortClassName(iterator.next().getJavaClass()));
1038
                    }
1073
                    }
1039
                }
1074
                }
1040
                writer.write(")");
1075
                writer.write(")");
Lines 1161-1166 Link Here
1161
     * The readTime may also be included in the cache key as it is constructed
1196
     * The readTime may also be included in the cache key as it is constructed
1162
     */
1197
     */
1163
    public CacheKey putInIdentityMap(Object domainObject, Object keys, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
1198
    public CacheKey putInIdentityMap(Object domainObject, Object keys, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
1199
        if (keys == null) {
1200
            return null;
1201
        }
1164
        ObjectBuilder builder = descriptor.getObjectBuilder();
1202
        ObjectBuilder builder = descriptor.getObjectBuilder();
1165
        Object implementation = builder.unwrapObject(domainObject, this.session);
1203
        Object implementation = builder.unwrapObject(domainObject, this.session);
1166
1204
Lines 1204-1212 Link Here
1204
                }
1242
                }
1205
            }
1243
            }
1206
        }
1244
        }
1207
        Object lookupParameters = parameters;
1245
        Object lookupParameters;
1208
        if (lookupParameters == null) {
1246
        if (parameters == null) {
1209
            lookupParameters = new NonSynchronizedVector(0);
1247
            lookupParameters = new CacheId(new Object[0]);
1248
        } else {
1249
            lookupParameters = new CacheId(parameters.toArray());
1210
        }
1250
        }
1211
        long queryTime = 0;
1251
        long queryTime = 0;
1212
        if (query.isObjectLevelReadQuery()) {
1252
        if (query.isObjectLevelReadQuery()) {
Lines 1249-1254 Link Here
1249
     * Remove the object from the object cache.
1289
     * Remove the object from the object cache.
1250
     */
1290
     */
1251
    public Object removeFromIdentityMap(Object key, Class domainClass, ClassDescriptor descriptor, Object objectToRemove) {
1291
    public Object removeFromIdentityMap(Object key, Class domainClass, ClassDescriptor descriptor, Object objectToRemove) {
1292
        if (key == null) {
1293
            return null;
1294
        }
1252
        IdentityMap map = getIdentityMap(descriptor, false);
1295
        IdentityMap map = getIdentityMap(descriptor, false);
1253
        Object value;
1296
        Object value;
1254
1297
Lines 1313-1318 Link Here
1313
     * Update the write lock value of the cache key associated with the given primary key,
1356
     * Update the write lock value of the cache key associated with the given primary key,
1314
     */
1357
     */
1315
    public void setWriteLockValue(Object primaryKey, Class theClass, Object writeLockValue) {
1358
    public void setWriteLockValue(Object primaryKey, Class theClass, Object writeLockValue) {
1359
        if (primaryKey == null) {
1360
            return;
1361
        }
1316
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
1362
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
1317
        IdentityMap map = getIdentityMap(descriptor, false);
1363
        IdentityMap map = getIdentityMap(descriptor, false);
1318
1364
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/LinkedCacheKey.java (-13 / +11 lines)
Lines 12-27 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.identitymaps;
13
package org.eclipse.persistence.internal.identitymaps;
14
14
15
import java.util.*;
16
17
/**
15
/**
18
 *    <p><b>Purpose</b>: Provides the capability to insert CacheKeys into a Linked List.
16
 * <p><b>Purpose</b>: Provides the capability to insert CacheKeys into a Linked List.
19
 *    <p><b>Responsibilities</b>:<ul>
17
 * <p><b>Responsibilities</b>:<ul>
20
 *    <li> Provide same capabilities as superclass.
18
 * <li> Provide same capabilities as superclass.
21
 *    <li> Maintain within linked list.
19
 * <li> Maintain within linked list.
22
 *    </ul>
20
 * </ul>
23
 *    @see CacheIdentityMap
21
 * @see CacheIdentityMap
24
 *    @since TOPLink/Java 1.0
22
 * @since TOPLink/Java 1.0
25
 */
23
 */
26
public class LinkedCacheKey extends CacheKey {
24
public class LinkedCacheKey extends CacheKey {
27
25
Lines 32-42 Link Here
32
    protected LinkedCacheKey next;
30
    protected LinkedCacheKey next;
33
31
34
    /**
32
    /**
35
     *    Initialize the newly allocated instance of this class.
33
     * Initialize the newly allocated instance of this class.
36
     *    @param object is the domain object.
34
     * @param object is the domain object.
37
     *    @param writeLockValue is the write lock value number.
35
     * @param writeLockValue is the write lock value number.
38
     */
36
     */
39
    public LinkedCacheKey(Vector primaryKey, Object object, Object writeLockValue, long readTime) {
37
    public LinkedCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
40
        super(primaryKey, object, writeLockValue, readTime);
38
        super(primaryKey, object, writeLockValue, readTime);
41
    }
39
    }
42
40
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/NoIdentityMap.java (-2 / +2 lines)
Lines 60-66 Link Here
60
     * Return null as no objects are cached.
60
     * Return null as no objects are cached.
61
     */
61
     */
62
    @Override
62
    @Override
63
    protected CacheKey getCacheKey(CacheKey searchKey) {
63
    public CacheKey getCacheKey(Object searchKey) {
64
        return null;
64
        return null;
65
    }
65
    }
66
    
66
    
Lines 68-74 Link Here
68
     * Return null as no objects are cached.
68
     * Return null as no objects are cached.
69
     */
69
     */
70
    @Override
70
    @Override
71
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey cacheKey) {
71
    protected CacheKey putCacheKeyIfAbsent(CacheKey cacheKey) {
72
        return null;
72
        return null;
73
    }
73
    }
74
74
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/QueueableWeakCacheKey.java (-2 / +1 lines)
Lines 2-8 Link Here
2
2
3
import java.lang.ref.ReferenceQueue;
3
import java.lang.ref.ReferenceQueue;
4
import java.lang.ref.WeakReference;
4
import java.lang.ref.WeakReference;
5
import java.util.Vector;
6
5
7
public class QueueableWeakCacheKey extends WeakCacheKey {
6
public class QueueableWeakCacheKey extends WeakCacheKey {
8
    // This the reference queue from the owning map that
7
    // This the reference queue from the owning map that
Lines 10-16 Link Here
10
    // makes for easy cleanup
9
    // makes for easy cleanup
11
    protected ReferenceQueue referenceQueue;
10
    protected ReferenceQueue referenceQueue;
12
11
13
    public QueueableWeakCacheKey(Vector primaryKey, Object object, Object writeLockValue, long readTime, ReferenceQueue refQueue) {
12
    public QueueableWeakCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime, ReferenceQueue refQueue) {
14
        super(primaryKey, object, writeLockValue, readTime);
13
        super(primaryKey, object, writeLockValue, readTime);
15
        this.referenceQueue = refQueue;
14
        this.referenceQueue = refQueue;
16
    }
15
    }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/UnitOfWorkCacheKey.java (-5 / +3 lines)
Lines 12-19 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.identitymaps;
13
package org.eclipse.persistence.internal.identitymaps;
14
14
15
import java.util.Vector;
16
17
/**
15
/**
18
 * Cache key used in the unit of work identity map.
16
 * Cache key used in the unit of work identity map.
19
 * This cache avoid locking as the unit of work is single threaded.
17
 * This cache avoid locking as the unit of work is single threaded.
Lines 22-36 Link Here
22
 */
20
 */
23
public class UnitOfWorkCacheKey extends CacheKey {
21
public class UnitOfWorkCacheKey extends CacheKey {
24
22
25
    public UnitOfWorkCacheKey(Vector primaryKeys) {
23
    public UnitOfWorkCacheKey(Object primaryKeys) {
26
        super(primaryKeys);
24
        super(primaryKeys);
27
    }
25
    }
28
26
29
    public UnitOfWorkCacheKey(Vector primaryKey, Object object, Object lockValue) {
27
    public UnitOfWorkCacheKey(Object primaryKey, Object object, Object lockValue) {
30
        super(primaryKey, object, lockValue);
28
        super(primaryKey, object, lockValue);
31
    }
29
    }
32
30
33
    public UnitOfWorkCacheKey(Vector primaryKey, Object object, Object lockValue, long readTime) {
31
    public UnitOfWorkCacheKey(Object primaryKey, Object object, Object lockValue, long readTime) {
34
        super(primaryKey, object, lockValue, readTime);
32
        super(primaryKey, object, lockValue, readTime);
35
    }
33
    }
36
34
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/UnitOfWorkIdentityMap.java (-24 / +31 lines)
Lines 34-40 Link Here
34
34
35
    @Override
35
    @Override
36
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
36
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
37
        return new UnitOfWorkCacheKey((Vector)primaryKey, object, writeLockValue, readTime);
37
        return new UnitOfWorkCacheKey(primaryKey, object, writeLockValue, readTime);
38
    }
38
    }
39
39
40
    /**
40
    /**
Lines 42-51 Link Here
42
     */
42
     */
43
    @Override
43
    @Override
44
    public CacheKey acquireDeferredLock(Object primaryKey) {
44
    public CacheKey acquireDeferredLock(Object primaryKey) {
45
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
45
        CacheKey cacheKey = getCacheKey(primaryKey);
46
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
47
        if (cacheKey == null) {
46
        if (cacheKey == null) {
48
            return newCacheKey;
47
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
48
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
49
            if (cacheKey == null) {
50
                return newCacheKey;
51
            }
49
        }
52
        }
50
        return cacheKey;
53
        return cacheKey;
51
    }
54
    }
Lines 55-64 Link Here
55
     */
58
     */
56
    @Override
59
    @Override
57
    public CacheKey acquireLock(Object primaryKey, boolean forMerge) {
60
    public CacheKey acquireLock(Object primaryKey, boolean forMerge) {
58
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
61
        CacheKey cacheKey = getCacheKey(primaryKey);
59
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
60
        if (cacheKey == null) {
62
        if (cacheKey == null) {
61
            return newCacheKey;
63
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
64
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
65
            if (cacheKey == null) {
66
                return newCacheKey;
67
            }
62
        }
68
        }
63
        return cacheKey;
69
        return cacheKey;
64
    }
70
    }
Lines 68-77 Link Here
68
     */
74
     */
69
    @Override
75
    @Override
70
    public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge) {
76
    public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge) {
71
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
77
        CacheKey cacheKey = getCacheKey(primaryKey);
72
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
73
        if (cacheKey == null) {
78
        if (cacheKey == null) {
74
            return newCacheKey;
79
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
80
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
81
            if (cacheKey == null) {
82
                return newCacheKey;
83
            }
75
        }
84
        }
76
        return cacheKey;
85
        return cacheKey;
77
    }
86
    }
Lines 81-90 Link Here
81
     */
90
     */
82
    @Override
91
    @Override
83
    public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) {
92
    public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) {
84
        CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
93
        CacheKey cacheKey = getCacheKey(primaryKey);
85
        CacheKey cacheKey = getCacheKeyIfAbsentPut(newCacheKey);
86
        if (cacheKey == null) {
94
        if (cacheKey == null) {
87
            return newCacheKey;
95
            CacheKey newCacheKey = createCacheKey(primaryKey, null, null);
96
            cacheKey = putCacheKeyIfAbsent(newCacheKey);
97
            if (cacheKey == null) {
98
                return newCacheKey;
99
            }
88
        }
100
        }
89
        return cacheKey;
101
        return cacheKey;
90
    }
102
    }
Lines 119-135 Link Here
119
    }
131
    }
120
    
132
    
121
    /**
133
    /**
122
     * Since a HashMap is used, must do a get and put.
134
     * Use hashmap put, as no concurrency in unit of work.
123
     * However HashMap is more efficient than a ConcurrentMap so is ok.
124
     */
135
     */
125
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey searchKey) {
136
    protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) {
126
        CacheKey cacheKey = getCacheKeys().get(searchKey);
137
        searchKey.setOwningMap(this);
127
        if (cacheKey == null) {
138
        this.cacheKeys.put(searchKey.getKey(), searchKey);
128
            searchKey.setOwningMap(this);
139
        return null;
129
            getCacheKeys().put(searchKey, searchKey);
130
            return null;
131
        }
132
        return cacheKey;
133
    }
140
    }
134
141
135
    /**
142
    /**
Lines 138-144 Link Here
138
    @Override
145
    @Override
139
    public Object remove(CacheKey cacheKey) {
146
    public Object remove(CacheKey cacheKey) {
140
        if (cacheKey != null) {
147
        if (cacheKey != null) {
141
            getCacheKeys().remove(cacheKey);
148
            this.cacheKeys.remove(cacheKey.getKey());
142
        } else {
149
        } else {
143
            return null;
150
            return null;
144
        }
151
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/WeakIdentityMap.java (-2 / +2 lines)
Lines 79-86 Link Here
79
     * Need to check for cleanup on put.
79
     * Need to check for cleanup on put.
80
     */
80
     */
81
    @Override
81
    @Override
82
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey searchKey) {
82
    protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) {
83
        CacheKey cacheKey = super.getCacheKeyIfAbsentPut(searchKey);
83
        CacheKey cacheKey = super.putCacheKeyIfAbsent(searchKey);
84
        if (cacheKey == null) {
84
        if (cacheKey == null) {
85
            checkCleanup();
85
            checkCleanup();
86
        }
86
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/WeakUnitOfWorkIdentityMap.java (-4 / +3 lines)
Lines 1-7 Link Here
1
package org.eclipse.persistence.internal.identitymaps;
1
package org.eclipse.persistence.internal.identitymaps;
2
2
3
import java.lang.ref.ReferenceQueue;
3
import java.lang.ref.ReferenceQueue;
4
import java.util.Vector;
5
4
6
import org.eclipse.persistence.descriptors.ClassDescriptor;
5
import org.eclipse.persistence.descriptors.ClassDescriptor;
7
6
Lines 39-53 Link Here
39
38
40
    @Override
39
    @Override
41
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
40
    public CacheKey createCacheKey(Object primaryKey, Object object, Object writeLockValue, long readTime) {
42
        return new QueueableWeakCacheKey((Vector)primaryKey, object, writeLockValue, readTime, referenceQueue);
41
        return new QueueableWeakCacheKey(primaryKey, object, writeLockValue, readTime, referenceQueue);
43
    }
42
    }
44
43
45
    /**
44
    /**
46
     * Need to check for cleanup on put.
45
     * Need to check for cleanup on put.
47
     */
46
     */
48
    @Override
47
    @Override
49
    protected CacheKey getCacheKeyIfAbsentPut(CacheKey searchKey) {
48
    protected CacheKey putCacheKeyIfAbsent(CacheKey searchKey) {
50
        CacheKey cacheKey = super.getCacheKeyIfAbsentPut(searchKey);
49
        CacheKey cacheKey = super.putCacheKeyIfAbsent(searchKey);
51
        if (cacheKey == null) {
50
        if (cacheKey == null) {
52
            checkCleanup();
51
            checkCleanup();
53
        }
52
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/indirection/TransparentIndirectionPolicy.java (-1 / +2 lines)
Lines 217-223 Link Here
217
     * This key will be used by a RemoteValueHolder.
217
     * This key will be used by a RemoteValueHolder.
218
     * OneToOneMappings should not be using transparent direction.
218
     * OneToOneMappings should not be using transparent direction.
219
     */
219
     */
220
    public Vector extractPrimaryKeyForReferenceObject(Object referenceObject, AbstractSession session) {
220
    @Override
221
    public Object extractPrimaryKeyForReferenceObject(Object referenceObject, AbstractSession session) {
221
        throw DescriptorException.invalidUseOfTransparentIndirection(this.getMapping());
222
        throw DescriptorException.invalidUseOfTransparentIndirection(this.getMapping());
222
    }
223
    }
223
224
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/oxm/documentpreservation/DescriptorLevelDocumentPreservationPolicy.java (-8 / +5 lines)
Lines 12-19 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.internal.oxm.documentpreservation;
13
package org.eclipse.persistence.internal.oxm.documentpreservation;
14
14
15
import java.util.Vector;
16
17
import org.w3c.dom.Element;
15
import org.w3c.dom.Element;
18
import org.w3c.dom.Node;
16
import org.w3c.dom.Node;
19
17
Lines 23-28 Link Here
23
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;
21
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;
24
import org.eclipse.persistence.oxm.mappings.XMLMapping;
22
import org.eclipse.persistence.oxm.mappings.XMLMapping;
25
import org.eclipse.persistence.oxm.record.DOMRecord;
23
import org.eclipse.persistence.oxm.record.DOMRecord;
24
import org.eclipse.persistence.internal.identitymaps.CacheId;
26
import org.eclipse.persistence.internal.identitymaps.CacheKey;
25
import org.eclipse.persistence.internal.identitymaps.CacheKey;
27
import org.eclipse.persistence.internal.oxm.WeakObjectWrapper;
26
import org.eclipse.persistence.internal.oxm.WeakObjectWrapper;
28
import org.eclipse.persistence.internal.sessions.AbstractSession;
27
import org.eclipse.persistence.internal.sessions.AbstractSession;
Lines 68-76 Link Here
68
        row.setSession(session);
67
        row.setSession(session);
69
        Object pk = xmlDescriptor.getObjectBuilder().extractPrimaryKeyFromRow(row, session);
68
        Object pk = xmlDescriptor.getObjectBuilder().extractPrimaryKeyFromRow(row, session);
70
        if (xmlDescriptor.shouldPreserveDocument() || xmlDescriptor.getPrimaryKeyFieldNames().size() > 0) {
69
        if (xmlDescriptor.shouldPreserveDocument() || xmlDescriptor.getPrimaryKeyFieldNames().size() > 0) {
71
            if ((pk == null) || (((Vector)pk).size() == 0)) {
70
            if ((pk == null) || (((CacheId)pk).getPrimaryKey().length == 0)) {
72
                pk = new Vector();
71
                pk = new CacheId(new Object[]{ new WeakObjectWrapper(obj) });
73
                ((Vector)pk).add(new WeakObjectWrapper(obj));
74
            }
72
            }
75
            CacheKey key = session.getIdentityMapAccessorInstance().acquireDeferredLock(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
73
            CacheKey key = session.getIdentityMapAccessorInstance().acquireDeferredLock(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
76
            if ((xmlDescriptor).shouldPreserveDocument()) {
74
            if ((xmlDescriptor).shouldPreserveDocument()) {
Lines 86-94 Link Here
86
        XMLDescriptor xmlDescriptor = (XMLDescriptor)session.getDescriptor(obj);
84
        XMLDescriptor xmlDescriptor = (XMLDescriptor)session.getDescriptor(obj);
87
        if(xmlDescriptor.shouldPreserveDocument()) {
85
        if(xmlDescriptor.shouldPreserveDocument()) {
88
            Object pk = xmlDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(obj, session);
86
            Object pk = xmlDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(obj, session);
89
            if ((pk == null) || (((Vector)pk).size() == 0)) {
87
            if ((pk == null) || (pk instanceof CacheId) && (((CacheId)pk).getPrimaryKey().length == 0)) {
90
                pk = new Vector();
88
                pk = new CacheId(new Object[]{ new WeakObjectWrapper(obj) });
91
                ((Vector)pk).addElement(new WeakObjectWrapper(obj));
92
            }
89
            }
93
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
90
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
94
            if(cacheKey != null && cacheKey.getRecord() != null) {
91
            if(cacheKey != null && cacheKey.getRecord() != null) {
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/oxm/Reference.java (-11 / +8 lines)
Lines 13-19 Link Here
13
package org.eclipse.persistence.internal.oxm;
13
package org.eclipse.persistence.internal.oxm;
14
14
15
import java.util.HashMap;
15
import java.util.HashMap;
16
import java.util.Vector;
17
import org.eclipse.persistence.oxm.mappings.XMLMapping;
16
import org.eclipse.persistence.oxm.mappings.XMLMapping;
18
import org.eclipse.persistence.oxm.sequenced.Setting;
17
import org.eclipse.persistence.oxm.sequenced.Setting;
19
18
Lines 29-35 Link Here
29
	protected XMLMapping mapping;		// mapping associated with this reference
28
	protected XMLMapping mapping;		// mapping associated with this reference
30
	protected Object sourceObject;		// the source object instance
29
	protected Object sourceObject;		// the source object instance
31
	protected Class targetClass;		// the reference class
30
	protected Class targetClass;		// the reference class
32
	protected Vector primaryKeys;		// primary key values for cache lookup - used in single case
31
	protected Object primaryKey;		// primary key values for cache lookup - used in single case
33
	protected HashMap primaryKeyMap;	// map of primary key values for cache lookup - used in collection case
32
	protected HashMap primaryKeyMap;	// map of primary key values for cache lookup - used in collection case
34
	private Setting setting;
33
	private Setting setting;
35
34
Lines 54-64 Link Here
54
	/**
53
	/**
55
	 * Constructor typically used in the single case.
54
	 * Constructor typically used in the single case.
56
	 */
55
	 */
57
	public Reference(XMLMapping mapping, Object source, Class target, Vector primaryKeys) {
56
	public Reference(XMLMapping mapping, Object source, Class target, Object primaryKey) {
58
		this.mapping = mapping;
57
		this.mapping = mapping;
59
		sourceObject = source;
58
		sourceObject = source;
60
		targetClass = target;
59
		targetClass = target;
61
		this.primaryKeys = primaryKeys;
60
		this.primaryKey = primaryKey;
62
	}
61
	}
63
62
64
	/**
63
	/**
Lines 86-93 Link Here
86
	 * 
85
	 * 
87
	 * @return
86
	 * @return
88
	 */
87
	 */
89
	public Vector getPrimaryKeys() {
88
	public Object getPrimaryKey() {
90
		return primaryKeys;
89
		return primaryKey;
91
	}
90
	}
92
91
93
	/**
92
	/**
Lines 109-120 Link Here
109
	}
108
	}
110
	
109
	
111
	/**
110
	/**
112
	 * Set the list of primary key values required to lookup
111
	 * Set the primary key value required to lookup
113
	 * the reference class in the cache.
112
	 * the reference class in the cache.
114
	 * 
115
	 * @param primaryKeys
116
	 */
113
	 */
117
	public void setPrimaryKeys(Vector primaryKeys) {
114
	public void setPrimaryKey(Object primaryKey) {
118
		this.primaryKeys = primaryKeys;
115
		this.primaryKey = primaryKey;
119
	}
116
	}
120
}
117
}
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/oxm/ReferenceResolver.java (-15 / +16 lines)
Lines 16-21 Link Here
16
import java.util.Iterator;
16
import java.util.Iterator;
17
import java.util.Vector;
17
import java.util.Vector;
18
18
19
import org.eclipse.persistence.internal.identitymaps.CacheId;
19
import org.eclipse.persistence.internal.queries.ContainerPolicy;
20
import org.eclipse.persistence.internal.queries.ContainerPolicy;
20
import org.eclipse.persistence.internal.sessions.AbstractSession;
21
import org.eclipse.persistence.internal.sessions.AbstractSession;
21
import org.eclipse.persistence.mappings.AttributeAccessor;
22
import org.eclipse.persistence.mappings.AttributeAccessor;
Lines 60-68 Link Here
60
61
61
    /**
62
    /**
62
     * INTERNAL:
63
     * INTERNAL:
63
     * Create vectors of primary key values to be used for cache lookup.  The map
64
     * Create primary key values to be used for cache lookup.  The map
64
     * of vectors on the reference is keyed on the reference descriptors primary
65
     * of primary keys on the reference is keyed on the reference descriptors primary
65
     * key field names.  Each of these vectors contains all of the values for a
66
     * key field names.  Each of these primary keys contains all of the values for a
66
     * particular key - in the order that they we read in from the document.  For
67
     * particular key - in the order that they we read in from the document.  For
67
     * example, if the key field names are A, B, and C, and there are three reference
68
     * example, if the key field names are A, B, and C, and there are three reference
68
     * object instances, then the hashmap would have the following:
69
     * object instances, then the hashmap would have the following:
Lines 81-111 Link Here
81
    		return;
82
    		return;
82
    	}
83
    	}
83
84
84
    	Vector pkVals;
85
    	CacheId pkVals;
85
    	boolean init = true;
86
    	boolean init = true;
86
87
87
    	// for each primary key field name
88
    	// for each primary key field name
88
    	for (Iterator pkFieldNameIt = pkFields.iterator(); pkFieldNameIt.hasNext(); ) {
89
    	for (Iterator pkFieldNameIt = pkFields.iterator(); pkFieldNameIt.hasNext(); ) {
89
    		pkVals = (Vector) reference.getPrimaryKeyMap().get(pkFieldNameIt.next());
90
    		pkVals = (CacheId) reference.getPrimaryKeyMap().get(pkFieldNameIt.next());
90
91
91
    		if (pkVals == null) {
92
    		if (pkVals == null) {
92
    			return;
93
    			return;
93
    		}
94
    		}
94
    		// initialize the list of pk vectors once and only once
95
    		// initialize the list of pk vectors once and only once
95
    		if (init) {
96
    		if (init) {
96
    			for (int i=0; i<pkVals.size(); i++) {
97
    			for (int i=0; i<pkVals.getPrimaryKey().length; i++) {
97
    				pks.add(new Vector());
98
    				pks.add(new CacheId(new Object[0]));
98
    			}
99
    			}
99
    			init = false;
100
    			init = false;
100
    		}
101
    		}
101
102
102
    		// now add each value for the current target key to it's own vector
103
    		// now add each value for the current target key to it's own vector
103
        	for (int i=0; i<pkVals.size(); i++) {
104
        	for (int i=0; i<pkVals.getPrimaryKey().length; i++) {
104
    			Object val = pkVals.get(i);
105
    			Object val = pkVals.getPrimaryKey()[i];
105
				((Vector) pks.get(i)).add(val);
106
                        ((CacheId)pks.get(i)).add(val);
106
    		}
107
    		}
107
    	}
108
    	}
108
    	reference.primaryKeys = pks;
109
    	reference.primaryKey = pks;
109
    }
110
    }
110
111
111
    /**
112
    /**
Lines 145-153 Link Here
145
                // create vectors of primary key values - one vector per reference instance
146
                // create vectors of primary key values - one vector per reference instance
146
                createPKVectorsFromMap(reference);
147
                createPKVectorsFromMap(reference);
147
                // loop over each pk vector and get object from cache - then add to collection and set on object
148
                // loop over each pk vector and get object from cache - then add to collection and set on object
148
                for (Iterator pkIt = reference.getPrimaryKeys().iterator(); pkIt.hasNext();) {
149
                for (Iterator pkIt = ((Vector)reference.getPrimaryKey()).iterator(); pkIt.hasNext();) {
149
                    Vector pkVector = (Vector) pkIt.next();
150
                    Object primaryKey = pkIt.next();
150
                    Object value = session.getIdentityMapAccessor().getFromIdentityMap(pkVector, reference.getTargetClass());
151
                    Object value = session.getIdentityMapAccessor().getFromIdentityMap(primaryKey, reference.getTargetClass());
151
152
152
                    if (value != null) {
153
                    if (value != null) {
153
                        cPolicy.addInto(value, container,  session);
154
                        cPolicy.addInto(value, container,  session);
Lines 173-179 Link Here
173
                    }
174
                    }
174
                }
175
                }
175
            } else if (reference.getMapping() instanceof XMLObjectReferenceMapping) {
176
            } else if (reference.getMapping() instanceof XMLObjectReferenceMapping) {
176
                Object value = session.getIdentityMapAccessor().getFromIdentityMap(reference.getPrimaryKeys(), reference.getTargetClass());
177
                Object value = session.getIdentityMapAccessor().getFromIdentityMap(reference.getPrimaryKey(), reference.getTargetClass());
177
                XMLObjectReferenceMapping mapping = (XMLObjectReferenceMapping)reference.getMapping();
178
                XMLObjectReferenceMapping mapping = (XMLObjectReferenceMapping)reference.getMapping();
178
                if (value != null) {
179
                if (value != null) {
179
                    mapping.setAttributeValueInObject(reference.getSourceObject(), value);
180
                    mapping.setAttributeValueInObject(reference.getSourceObject(), value);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/oxm/XMLObjectBuilder.java (-9 / +7 lines)
Lines 16-22 Link Here
16
import java.util.ArrayList;
16
import java.util.ArrayList;
17
import java.util.Enumeration;
17
import java.util.Enumeration;
18
import java.util.List;
18
import java.util.List;
19
import java.util.Vector;
20
import java.util.Map.Entry;
19
import java.util.Map.Entry;
21
20
22
import javax.xml.namespace.QName;
21
import javax.xml.namespace.QName;
Lines 28-33 Link Here
28
import org.eclipse.persistence.internal.descriptors.Namespace;
27
import org.eclipse.persistence.internal.descriptors.Namespace;
29
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
28
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
30
import org.eclipse.persistence.internal.helper.DatabaseField;
29
import org.eclipse.persistence.internal.helper.DatabaseField;
30
import org.eclipse.persistence.internal.identitymaps.CacheId;
31
import org.eclipse.persistence.internal.identitymaps.CacheKey;
31
import org.eclipse.persistence.internal.identitymaps.CacheKey;
32
import org.eclipse.persistence.internal.oxm.WeakObjectWrapper;
32
import org.eclipse.persistence.internal.oxm.WeakObjectWrapper;
33
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
33
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
Lines 84-92 Link Here
84
    public AbstractRecord buildRow(Object object, AbstractSession session, DatabaseField xmlField, XMLRecord parentRecord, boolean addXsiType) {
84
    public AbstractRecord buildRow(Object object, AbstractSession session, DatabaseField xmlField, XMLRecord parentRecord, boolean addXsiType) {
85
        if (isXmlDescriptor() && ((XMLDescriptor)getDescriptor()).shouldPreserveDocument()) {
85
        if (isXmlDescriptor() && ((XMLDescriptor)getDescriptor()).shouldPreserveDocument()) {
86
            Object pk = extractPrimaryKeyFromObject(object, session);
86
            Object pk = extractPrimaryKeyFromObject(object, session);
87
            if ((pk == null) || (((Vector)pk).size() == 0)) {
87
            if ((pk == null) || (pk instanceof CacheId) && (((CacheId)pk).getPrimaryKey().length == 0)) {
88
                pk = new Vector();
88
                pk = new CacheId(new Object[]{ new WeakObjectWrapper(object) });
89
                ((Vector)pk).add(new WeakObjectWrapper(object));
90
            }
89
            }
91
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, getDescriptor().getJavaClass(), getDescriptor());
90
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, getDescriptor().getJavaClass(), getDescriptor());
92
            if ((cacheKey != null) && (cacheKey.getRecord() != null)) {
91
            if ((cacheKey != null) && (cacheKey.getRecord() != null)) {
Lines 293-301 Link Here
293
        }
292
        }
294
        concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false);
293
        concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, databaseRow, query, joinManager, false);
295
        if (isXmlDescriptor() && ((XMLDescriptor)concreteDescriptor).getPrimaryKeyFieldNames().size() > 0) {
294
        if (isXmlDescriptor() && ((XMLDescriptor)concreteDescriptor).getPrimaryKeyFieldNames().size() > 0) {
296
            if ((pk == null) || (((Vector)pk).size() == 0)) {
295
            if ((pk == null) || (((CacheId)pk).getPrimaryKey().length == 0)) {
297
                pk = new Vector();
296
                pk = new CacheId(new Object[]{ new WeakObjectWrapper(domainObject) });
298
                ((Vector)pk).add(new WeakObjectWrapper(domainObject));
299
            }
297
            }
300
            CacheKey key = query.getSession().getIdentityMapAccessorInstance().acquireDeferredLock(pk, concreteDescriptor.getJavaClass(), concreteDescriptor);
298
            CacheKey key = query.getSession().getIdentityMapAccessorInstance().acquireDeferredLock(pk, concreteDescriptor.getJavaClass(), concreteDescriptor);
301
            if (((XMLDescriptor)concreteDescriptor).shouldPreserveDocument()) {
299
            if (((XMLDescriptor)concreteDescriptor).shouldPreserveDocument()) {
Lines 373-381 Link Here
373
    }
371
    }
374
372
375
    public void writeOutMappings(XMLRecord row, Object object, AbstractSession session) {
373
    public void writeOutMappings(XMLRecord row, Object object, AbstractSession session) {
376
        Vector mappings = getDescriptor().getMappings();
374
        List<DatabaseMapping> mappings = getDescriptor().getMappings();
377
        for (int index = 0; index < mappings.size(); index++) {
375
        for (int index = 0; index < mappings.size(); index++) {
378
            DatabaseMapping mapping = (DatabaseMapping)mappings.get(index);
376
            DatabaseMapping mapping = mappings.get(index);
379
            mapping.writeFromObjectIntoRow(object, row, session);
377
            mapping.writeFromObjectIntoRow(object, row, session);
380
        }
378
        }
381
    }
379
    }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/DatabaseQueryMechanism.java (-15 / +10 lines)
Lines 26-32 Link Here
26
import org.eclipse.persistence.internal.sessions.*;
26
import org.eclipse.persistence.internal.sessions.*;
27
import org.eclipse.persistence.sessions.DatabaseRecord;
27
import org.eclipse.persistence.sessions.DatabaseRecord;
28
import org.eclipse.persistence.tools.profiler.QueryMonitor;
28
import org.eclipse.persistence.tools.profiler.QueryMonitor;
29
import org.eclipse.persistence.internal.identitymaps.CacheKey;
30
import org.eclipse.persistence.expressions.*;
29
import org.eclipse.persistence.expressions.*;
31
import org.eclipse.persistence.queries.*;
30
import org.eclipse.persistence.queries.*;
32
import org.eclipse.persistence.exceptions.*;
31
import org.eclipse.persistence.exceptions.*;
Lines 119-144 Link Here
119
        
118
        
120
        ClassDescriptor descriptor = getDescriptor();
119
        ClassDescriptor descriptor = getDescriptor();
121
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
120
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
122
        Vector primaryKeyValues = new Vector(primaryKeyFields.size());
123
        
121
        
122
        // Check that the query is by primary key.
124
        for (DatabaseField primaryKeyField : primaryKeyFields) {
123
        for (DatabaseField primaryKeyField : primaryKeyFields) {
125
            if (queryFields.contains(primaryKeyField)) {
124
            if (!queryFields.contains(primaryKeyField)) {
126
                Object value = translationRow.get(primaryKeyField);
127
            
128
                if (value == null) {
129
                    return null;
130
                } else {
131
                    primaryKeyValues.add(value);    
132
                }
133
            } else {
134
                return null;
125
                return null;
135
            }
126
            }
136
        }
127
        }
128
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(translationRow, session);
129
        if (primaryKey == null) {
130
            return null;
131
        }
137
        
132
        
138
        if (descriptor.shouldAcquireCascadedLocks()) {
133
        if (descriptor.shouldAcquireCascadedLocks()) {
139
            return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKeyValues, getReadObjectQuery().getReferenceClass(), false, descriptor);
134
            return session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
140
        } else {
135
        } else {
141
            return session.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKeyValues, getReadObjectQuery().getReferenceClass(), false, descriptor);
136
            return session.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, getReadObjectQuery().getReferenceClass(), false, descriptor);
142
        }        
137
        }        
143
    }
138
    }
144
139
Lines 797-803 Link Here
797
            if (objectChangeSet != null) {
792
            if (objectChangeSet != null) {
798
                updateChangeSet(getDescriptor(), objectChangeSet, row, object);
793
                updateChangeSet(getDescriptor(), objectChangeSet, row, object);
799
                if (primaryKey != null) {
794
                if (primaryKey != null) {
800
                    objectChangeSet.setCacheKey(new CacheKey(primaryKey));
795
                    objectChangeSet.setId(primaryKey);
801
                }
796
                }
802
            }
797
            }
803
        }
798
        }
Lines 934-940 Link Here
934
            }
929
            }
935
            if (objectChangeSet != null) {
930
            if (objectChangeSet != null) {
936
                updateChangeSet(descriptor, objectChangeSet, sequenceNumberField, object);
931
                updateChangeSet(descriptor, objectChangeSet, sequenceNumberField, object);
937
                objectChangeSet.setCacheKey(new CacheKey(primaryKey));
932
                objectChangeSet.setId(primaryKey);
938
            }
933
            }
939
        }
934
        }
940
    }
935
    }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/ExpressionQueryMechanism.java (-9 / +10 lines)
Lines 712-717 Link Here
712
     * This is only called from read object query.
712
     * This is only called from read object query.
713
     * The query has already checked that the cache should be checked.
713
     * The query has already checked that the cache should be checked.
714
     */
714
     */
715
    @Override
715
    public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
716
    public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
716
        // For bug 2782991 a list of nearly 20 problems with this method have
717
        // For bug 2782991 a list of nearly 20 problems with this method have
717
        // been fixed.
718
        // been fixed.
Lines 760-769 Link Here
760
            } else {
761
            } else {
761
                cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
762
                cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
762
            }
763
            }
763
            // Also check if key is null, cannot exist.
764
            if (((Vector)selectionKey).contains(null)) {
765
                return InvalidObject.instance;
766
            }
767
        } else {
764
        } else {
768
            // 2: If selection criteria null, take any instance in cache.
765
            // 2: If selection criteria null, take any instance in cache.
769
            //
766
            //
Lines 781-796 Link Here
781
                // primary key only this will become the final check.
778
                // primary key only this will become the final check.
782
                if ((selectionKey != null) || query.shouldCheckCacheByExactPrimaryKey()) {
779
                if ((selectionKey != null) || query.shouldCheckCacheByExactPrimaryKey()) {
783
                    if (selectionKey != null) {
780
                    if (selectionKey != null) {
781
                        // Check if key is invalid (null), cannot exist.
782
                        if (selectionKey == InvalidObject.instance) {
783
                            return selectionKey;
784
                        }
784
                        if (descriptor.shouldAcquireCascadedLocks()) {
785
                        if (descriptor.shouldAcquireCascadedLocks()) {
785
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
786
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
786
                        } else {
787
                        } else {
787
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
788
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
788
                        }
789
                        }
789
                        // Because it was exact primary key if the lookup failed then it is not there.
790
                        // Because it was exact primary key if the lookup failed then it is not there.                        
790
                        // Also check if key is null, cannot exist.
791
                        if (((Vector)selectionKey).contains(null)) {
792
                            return InvalidObject.instance;
793
                        }
794
                    }
791
                    }
795
                } else {
792
                } else {
796
                    // 4: If can extract inexact primary key, find one object by primary key and
793
                    // 4: If can extract inexact primary key, find one object by primary key and
Lines 798-803 Link Here
798
                    // rule out a cache hit.
795
                    // rule out a cache hit.
799
                    Object inexactSelectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(false, selectionCriteria, translationRow, session);// Check for any primary key in expression, may have other stuff.
796
                    Object inexactSelectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(false, selectionCriteria, translationRow, session);// Check for any primary key in expression, may have other stuff.
800
                    if (inexactSelectionKey != null) {
797
                    if (inexactSelectionKey != null) {
798
                        // Check if key is invalid (null), cannot exist.
799
                        if (selectionKey == InvalidObject.instance) {
800
                            return selectionKey;
801
                        }
801
                        // PERF: Only use deferred lock when required.
802
                        // PERF: Only use deferred lock when required.
802
                        if (descriptor.shouldAcquireCascadedLocks()) {
803
                        if (descriptor.shouldAcquireCascadedLocks()) {
803
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
804
                            cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMapWithDeferredLock(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/JoinedAttributeManager.java (-11 / +9 lines)
Lines 34-40 Link Here
34
import org.eclipse.persistence.internal.expressions.ForUpdateOfClause;
34
import org.eclipse.persistence.internal.expressions.ForUpdateOfClause;
35
import org.eclipse.persistence.exceptions.QueryException;
35
import org.eclipse.persistence.exceptions.QueryException;
36
import org.eclipse.persistence.internal.helper.NonSynchronizedSubVector;
36
import org.eclipse.persistence.internal.helper.NonSynchronizedSubVector;
37
import org.eclipse.persistence.internal.identitymaps.CacheKey;
38
import org.eclipse.persistence.mappings.DatabaseMapping;
37
import org.eclipse.persistence.mappings.DatabaseMapping;
39
import org.eclipse.persistence.queries.ObjectBuildingQuery;
38
import org.eclipse.persistence.queries.ObjectBuildingQuery;
40
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
39
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
Lines 80-86 Link Here
80
    protected transient List<AbstractRecord> dataResults;
79
    protected transient List<AbstractRecord> dataResults;
81
80
82
    /** Stored all row results to -m joining by cache key. */
81
    /** Stored all row results to -m joining by cache key. */
83
    protected transient Map<CacheKey, List> dataResultsByPrimaryKey;
82
    protected transient Map<Object, List<AbstractRecord>> dataResultsByPrimaryKey;
84
    
83
    
85
    /** Stores the descriptor that these joins apply on */
84
    /** Stores the descriptor that these joins apply on */
86
    protected transient ClassDescriptor descriptor;
85
    protected transient ClassDescriptor descriptor;
Lines 737-750 Link Here
737
    /**
736
    /**
738
     * Return all of the rows fetched by the query by cache-key, used for 1-m joining.
737
     * Return all of the rows fetched by the query by cache-key, used for 1-m joining.
739
     */
738
     */
740
    public Map<CacheKey, List> getDataResultsByPrimaryKey() {
739
    public Map<Object, List<AbstractRecord>> getDataResultsByPrimaryKey() {
741
        return dataResultsByPrimaryKey;
740
        return dataResultsByPrimaryKey;
742
    }
741
    }
743
    
742
    
744
    /**
743
    /**
745
     * Set all of the rows fetched by the query by cache-key, used for 1-m joining.
744
     * Set all of the rows fetched by the query by cache-key, used for 1-m joining.
746
     */
745
     */
747
    protected void setDataResultsByPrimaryKey(Map<CacheKey, List> dataResultsByPrimaryKey) {
746
    protected void setDataResultsByPrimaryKey(Map<Object, List<AbstractRecord>> dataResultsByPrimaryKey) {
748
        this.dataResultsByPrimaryKey = dataResultsByPrimaryKey;
747
        this.dataResultsByPrimaryKey = dataResultsByPrimaryKey;
749
    }
748
    }
750
    
749
    
Lines 763-770 Link Here
763
    protected void processDataResults(AbstractSession session) {
762
    protected void processDataResults(AbstractSession session) {
764
        this.dataResultsByPrimaryKey = new HashMap();
763
        this.dataResultsByPrimaryKey = new HashMap();
765
        int size = this.dataResults.size();
764
        int size = this.dataResults.size();
766
        CacheKey lastCacheKey = null;
765
        Object lastKey = null;
767
        List childRows = null;
766
        List<AbstractRecord> childRows = null;
768
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
767
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
769
        int parentIndex = getParentResultIndex();
768
        int parentIndex = getParentResultIndex();
770
        for (int dataResultsIndex = 0; dataResultsIndex < size; dataResultsIndex++) {
769
        for (int dataResultsIndex = 0; dataResultsIndex < size; dataResultsIndex++) {
Lines 780-797 Link Here
780
            Object sourceKey = builder.extractPrimaryKeyFromRow(parentRow, session);
779
            Object sourceKey = builder.extractPrimaryKeyFromRow(parentRow, session);
781
            // May be any outer-join so ignore null.
780
            // May be any outer-join so ignore null.
782
            if (sourceKey != null) {
781
            if (sourceKey != null) {
783
                CacheKey sourceCacheKey = new CacheKey(sourceKey);
782
                if ((lastKey != null) && lastKey.equals(sourceKey)) {
784
                if ((lastCacheKey != null) && lastCacheKey.equals(sourceCacheKey)) {
785
                    childRows.add(row);
783
                    childRows.add(row);
786
                    if (shouldFilterDuplicates()) {
784
                    if (shouldFilterDuplicates()) {
787
                        // Also null out the row because it is a duplicate to avoid object building processing it.
785
                        // Also null out the row because it is a duplicate to avoid object building processing it.
788
                        this.dataResults.set(dataResultsIndex, null);
786
                        this.dataResults.set(dataResultsIndex, null);
789
                    }
787
                    }
790
                } else {
788
                } else {
791
                    childRows =  this.dataResultsByPrimaryKey.get(sourceCacheKey);
789
                    childRows =  this.dataResultsByPrimaryKey.get(sourceKey);
792
                    if (childRows == null) {
790
                    if (childRows == null) {
793
                        childRows = new ArrayList();
791
                        childRows = new ArrayList();
794
                        this.dataResultsByPrimaryKey.put(sourceCacheKey, childRows);
792
                        this.dataResultsByPrimaryKey.put(sourceKey, childRows);
795
                    } else {
793
                    } else {
796
                        if (shouldFilterDuplicates()) {
794
                        if (shouldFilterDuplicates()) {
797
                            // Also null out the row because it is a duplicate to avoid object building processing it.
795
                            // Also null out the row because it is a duplicate to avoid object building processing it.
Lines 799-805 Link Here
799
                        }
797
                        }
800
                    }
798
                    }
801
                    childRows.add(row);
799
                    childRows.add(row);
802
                    lastCacheKey = sourceCacheKey;
800
                    lastKey = sourceKey;
803
                }
801
                }
804
            }
802
            }
805
        }
803
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/queries/OrderedListContainerPolicy.java (-7 / +7 lines)
Lines 455-477 Link Here
455
                        
455
                        
456
                        //if objectToRemove is null, we can't look it up in the collection. 
456
                        //if objectToRemove is null, we can't look it up in the collection. 
457
                        // This should not happen unless identity is lost.
457
                        // This should not happen unless identity is lost.
458
                        if (objectToRemove!=null){
458
                        if (objectToRemove != null) {
459
                            Integer index = changeObject.getIndex();
459
                            Integer index = changeObject.getIndex();
460
                            if (index!=null){
460
                            if (index!=null){
461
                                if (objectToRemove.equals(get(index, valueOfTarget, mergeManager.getSession()))) {
461
                                if (objectToRemove.equals(get(index, valueOfTarget, mergeManager.getSession()))) {
462
                                    removeFromAtIndex(index, valueOfTarget);
462
                                    removeFromAtIndex(index, valueOfTarget);
463
                                } else {
463
                                } else {
464
                                    //Object is in the cache, but the collection doesn't have it at the location we expect
464
                                    // Object is in the cache, but the collection doesn't have it at the location we expect
465
                                    // Collection is invalid with respect to these changes, so invalidate the parent and abort 
465
                                    // Collection is invalid with respect to these changes, so invalidate the parent and abort 
466
                                    Vector key = ((org.eclipse.persistence.internal.sessions.ObjectChangeSet)changeRecord.getOwner()).getPrimaryKeys();
466
                                    Object key = changeRecord.getOwner().getId();
467
                                    parentSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(parentSession));
467
                                    parentSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(parentSession));
468
                                    return;
468
                                    return;
469
                                }
469
                                }
470
                            } else{
470
                            } else {
471
                                removeFrom(objectToRemove, valueOfTarget, parentSession);
471
                                removeFrom(objectToRemove, valueOfTarget, parentSession);
472
                            }
472
                            }
473
                            
473
                            
474
                            if ( (! mergeManager.shouldMergeChangesIntoDistributedCache()) && changeRecord.getMapping().isPrivateOwned()) {
474
                            if ((! mergeManager.shouldMergeChangesIntoDistributedCache()) && changeRecord.getMapping().isPrivateOwned()) {
475
                                // Check that the object was actually removed and not moved.
475
                                // Check that the object was actually removed and not moved.
476
                                if (objectRemoved) {
476
                                if (objectRemoved) {
477
                                    mergeManager.registerRemovedNewObjectIfRequired(objectChanges.getUnitOfWorkClone());
477
                                    mergeManager.registerRemovedNewObjectIfRequired(objectChanges.getUnitOfWorkClone());
Lines 480-486 Link Here
480
                        }
480
                        }
481
                        
481
                        
482
                        
482
                        
483
                    } else {//getChangeType == add
483
                    } else { //getChangeType == add
484
                        boolean objectAdded = changeRecord.getAddObjectList().containsKey(objectChanges);
484
                        boolean objectAdded = changeRecord.getAddObjectList().containsKey(objectChanges);
485
                        Object object = null;
485
                        Object object = null;
486
                        // The object was actually added and not moved.
486
                        // The object was actually added and not moved.
Lines 538-544 Link Here
538
                        
538
                        
539
                            //Object is either not in the cache, or not at the location we expect
539
                            //Object is either not in the cache, or not at the location we expect
540
                            // Collection is invalid with respect to these changes, so invalidate the parent and abort 
540
                            // Collection is invalid with respect to these changes, so invalidate the parent and abort 
541
                            Vector key = ((org.eclipse.persistence.internal.sessions.ObjectChangeSet)changeRecord.getOwner()).getPrimaryKeys();
541
                            Object key = changeRecord.getOwner().getId();
542
                            parentSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(parentSession));
542
                            parentSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(parentSession));
543
                            return;
543
                            return;
544
                        }
544
                        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/AggregateObjectChangeSet.java (-2 / +2 lines)
Lines 13-19 Link Here
13
package org.eclipse.persistence.internal.sessions;
13
package org.eclipse.persistence.internal.sessions;
14
14
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
16
import org.eclipse.persistence.internal.identitymaps.CacheKey;
17
16
18
public class AggregateObjectChangeSet extends ObjectChangeSet {
17
public class AggregateObjectChangeSet extends ObjectChangeSet {
19
18
Lines 31-37 Link Here
31
        super(primaryKey, descriptor, cloneObject, parent, isNew);
30
        super(primaryKey, descriptor, cloneObject, parent, isNew);
32
    }
31
    }
33
32
34
    public CacheKey CacheKey() {
33
    @Override
34
    public Object getId() {
35
        return null;
35
        return null;
36
    }
36
    }
37
37
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/CommitOrderDependencyNode.java (-3 / +3 lines)
Lines 205-215 Link Here
205
        results.addElement(node);
205
        results.addElement(node);
206
206
207
        if (node.getDescriptor().hasInheritance()) {
207
        if (node.getDescriptor().hasInheritance()) {
208
            InheritancePolicy p = node.getDescriptor().getInheritancePolicy();
208
            InheritancePolicy policy = node.getDescriptor().getInheritancePolicy();
209
209
210
            // For bug 3019934 replace getChildDescriptors with getAllChildDescriptors.
210
            // For bug 3019934 replace getChildDescriptors with getAllChildDescriptors.
211
            for (Enumeration e = p.getAllChildDescriptors().elements(); e.hasMoreElements();) {
211
            for (ClassDescriptor child : policy.getAllChildDescriptors()) {
212
                results.addElement(getOwner().nodeFor((ClassDescriptor)e.nextElement()));
212
                results.add(getOwner().nodeFor(child));
213
            }
213
            }
214
        }
214
        }
215
        return results;
215
        return results;
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IdentityMapAccessor.java (-15 / +29 lines)
Lines 178-190 Link Here
178
    }
178
    }
179
179
180
    /**
180
    /**
181
     * Convert the primary key Vector into a primary key object.
182
     * This is used to support the old deprecated Vector API.
183
     */
184
    public Object primaryKeyFromVector(Vector primaryKeyVector) {
185
        if (primaryKeyVector == null) {
186
            return null;
187
        } else if (primaryKeyVector.size() == 1) {
188
            return primaryKeyVector.get(0);            
189
        } else {
190
            return new CacheId(primaryKeyVector.toArray());
191
        }
192
    }
193
    
194
    /**
181
     * ADVANCED:
195
     * ADVANCED:
182
     * Return if their is an object for the primary key.
196
     * Return if their is an object for the primary key.
183
     */
197
     */
184
    @Deprecated
198
    @Deprecated
185
    public boolean containsObjectInIdentityMap(Vector primaryKey, Class theClass) {
199
    public boolean containsObjectInIdentityMap(Vector primaryKey, Class theClass) {
186
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
200
        return containsObjectInIdentityMap(primaryKeyFromVector(primaryKey), theClass);
187
        return containsObjectInIdentityMap(primaryKey, theClass, descriptor);
188
    }
201
    }
189
202
190
    /**
203
    /**
Lines 331-337 Link Here
331
     */
344
     */
332
    @Deprecated
345
    @Deprecated
333
    public Object getFromIdentityMap(Vector primaryKey, Class theClass) {
346
    public Object getFromIdentityMap(Vector primaryKey, Class theClass) {
334
        return getFromIdentityMap(primaryKey, theClass, true);
347
        return getFromIdentityMap(primaryKeyFromVector(primaryKey), theClass);
335
    }
348
    }
336
349
337
    /**
350
    /**
Lines 357-363 Link Here
357
     */
370
     */
358
    @Deprecated
371
    @Deprecated
359
    public Object getFromIdentityMap(Vector primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects) {
372
    public Object getFromIdentityMap(Vector primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects) {
360
        return getFromIdentityMap(primaryKey, theClass, shouldReturnInvalidatedObjects, getSession().getDescriptor(theClass));
373
        return getFromIdentityMap(primaryKeyFromVector(primaryKey), theClass, shouldReturnInvalidatedObjects);
361
    }
374
    }
362
375
363
    /**
376
    /**
Lines 574-580 Link Here
574
     */
587
     */
575
    @Deprecated
588
    @Deprecated
576
    public Object getWriteLockValue(Vector primaryKey, Class theClass) {
589
    public Object getWriteLockValue(Vector primaryKey, Class theClass) {
577
        return getWriteLockValue(primaryKey, theClass, getSession().getDescriptor(theClass));
590
        return getWriteLockValue(primaryKeyFromVector(primaryKey), theClass);
578
    }
591
    }
579
592
580
    /**
593
    /**
Lines 662-668 Link Here
662
     */
675
     */
663
    @Deprecated
676
    @Deprecated
664
    public void invalidateObject(Vector primaryKey, Class theClass, boolean invalidateCluster) {
677
    public void invalidateObject(Vector primaryKey, Class theClass, boolean invalidateCluster) {
665
        invalidateObject((Object)primaryKey, theClass, invalidateCluster);
678
        invalidateObject(primaryKeyFromVector(primaryKey), theClass, invalidateCluster);
666
    }
679
    }
667
680
668
    /**
681
    /**
Lines 673-679 Link Here
673
     */
686
     */
674
    @Deprecated
687
    @Deprecated
675
    public void invalidateObject(Vector primaryKey, Class theClass) {
688
    public void invalidateObject(Vector primaryKey, Class theClass) {
676
        invalidateObject(primaryKey, theClass, false);
689
        invalidateObject(primaryKeyFromVector(primaryKey), theClass);
677
    }
690
    }
678
691
679
    /**
692
    /**
Lines 692-700 Link Here
692
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
705
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
693
     */
706
     */
694
    public void invalidateObject(Object primaryKey, Class theClass, boolean invalidateCluster) {
707
    public void invalidateObject(Object primaryKey, Class theClass, boolean invalidateCluster) {
708
        if (primaryKey == null) {
709
            return;
710
        }
695
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
711
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
696
        //forward the call to getCacheKeyForObject locally in case subclasses overload
712
        //forward the call to getCacheKeyForObject locally in case subclasses overload
697
        CacheKey key = this.getCacheKeyForObjectForLock(primaryKey, theClass, descriptor);
713
        CacheKey key = getCacheKeyForObjectForLock(primaryKey, theClass, descriptor);
698
        if (key != null) {
714
        if (key != null) {
699
            key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
715
            key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
700
        }
716
        }
Lines 840-846 Link Here
840
     */
856
     */
841
    @Deprecated
857
    @Deprecated
842
    public boolean isValid(Vector primaryKey, Class theClass) {
858
    public boolean isValid(Vector primaryKey, Class theClass) {
843
        return isValid((Object)primaryKey, theClass);
859
        return isValid(primaryKeyFromVector(primaryKey), theClass);
844
    }
860
    }
845
861
846
    /**
862
    /**
Lines 914-920 Link Here
914
     */
930
     */
915
    @Deprecated
931
    @Deprecated
916
    public Object putInIdentityMap(Object object, Vector key) {
932
    public Object putInIdentityMap(Object object, Vector key) {
917
        return putInIdentityMap(object, key, null);
933
        return putInIdentityMap(object, primaryKeyFromVector(key));
918
    }
934
    }
919
935
920
    /**
936
    /**
Lines 953-960 Link Here
953
     */
969
     */
954
    @Deprecated
970
    @Deprecated
955
    public Object putInIdentityMap(Object object, Vector key, Object writeLockValue, long readTime) {
971
    public Object putInIdentityMap(Object object, Vector key, Object writeLockValue, long readTime) {
956
        ClassDescriptor descriptor = getSession().getDescriptor(object);
972
        return putInIdentityMap(object, primaryKeyFromVector(key), writeLockValue, readTime);
957
        return putInIdentityMap(object, key, writeLockValue, readTime, descriptor);
958
    }
973
    }
959
974
960
    /**
975
    /**
Lines 1030-1037 Link Here
1030
     */
1045
     */
1031
    @Deprecated
1046
    @Deprecated
1032
    public Object removeFromIdentityMap(Vector key, Class theClass) {
1047
    public Object removeFromIdentityMap(Vector key, Class theClass) {
1033
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
1048
        return removeFromIdentityMap(primaryKeyFromVector(key), theClass);
1034
        return removeFromIdentityMap(key, theClass, descriptor, null);
1035
    }
1049
    }
1036
    
1050
    
1037
    /**
1051
    /**
Lines 1082-1088 Link Here
1082
     */
1096
     */
1083
    @Deprecated
1097
    @Deprecated
1084
    public void updateWriteLockValue(Vector primaryKey, Class theClass, Object writeLockValue) {
1098
    public void updateWriteLockValue(Vector primaryKey, Class theClass, Object writeLockValue) {
1085
        updateWriteLockValue((Object)primaryKey, theClass, writeLockValue);
1099
        updateWriteLockValue(primaryKeyFromVector(primaryKey), theClass, writeLockValue);
1086
    }
1100
    }
1087
1101
1088
    /**
1102
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/MergeManager.java (-56 / +55 lines)
Lines 24-29 Link Here
24
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
24
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
25
import org.eclipse.persistence.exceptions.*;
25
import org.eclipse.persistence.exceptions.*;
26
import org.eclipse.persistence.internal.helper.linkedlist.LinkedNode;
26
import org.eclipse.persistence.internal.helper.linkedlist.LinkedNode;
27
import org.eclipse.persistence.queries.DoesExistQuery;
27
import org.eclipse.persistence.sessions.remote.*;
28
import org.eclipse.persistence.sessions.remote.*;
28
import org.eclipse.persistence.internal.sessions.remote.*;
29
import org.eclipse.persistence.internal.sessions.remote.*;
29
import org.eclipse.persistence.internal.queries.ContainerPolicy;
30
import org.eclipse.persistence.internal.queries.ContainerPolicy;
Lines 56-63 Link Here
56
    /** Used to store the list of locks that this merge manager has acquired for this merge */
57
    /** Used to store the list of locks that this merge manager has acquired for this merge */
57
    protected ArrayList<CacheKey> acquiredLocks;
58
    protected ArrayList<CacheKey> acquiredLocks;
58
59
59
    /** If this variable is not null then the mergemanager is waiting on a particular cacheKey */
60
    /** If this variable is not null then the mergemanager is waiting on a particular primary key */
60
    protected CacheKey writeLockQueued;
61
    protected Object writeLockQueued;
61
62
62
    /** Stores the node that holds this mergemanager within the WriteLocksManager queue */
63
    /** Stores the node that holds this mergemanager within the WriteLocksManager queue */
63
    protected LinkedNode queueNode;
64
    protected LinkedNode queueNode;
Lines 223-229 Link Here
223
     * INTENRAL:
224
     * INTENRAL:
224
     * Used to get the object that the merge manager is waiting on, in order to acquire locks
225
     * Used to get the object that the merge manager is waiting on, in order to acquire locks
225
     */
226
     */
226
    public CacheKey getWriteLockQueued() {
227
    public Object getWriteLockQueued() {
227
        return this.writeLockQueued;
228
        return this.writeLockQueued;
228
    }
229
    }
229
    
230
    
Lines 404-410 Link Here
404
405
405
        // Perform invalidation of a cached object (when set on the ChangeSet) to avoid refreshing or merging
406
        // Perform invalidation of a cached object (when set on the ChangeSet) to avoid refreshing or merging
406
        if (changeSet.getSynchronizationType() == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS) {
407
        if (changeSet.getSynchronizationType() == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS) {
407
            session.getIdentityMapAccessorInstance().invalidateObject(changeSet.getPrimaryKeys(), localClassType);
408
            session.getIdentityMapAccessorInstance().invalidateObject(changeSet.getId(), localClassType);
408
            return original;
409
            return original;
409
        }
410
        }
410
        
411
        
Lines 415-441 Link Here
415
                // Rebuild the version value from user format i.e the change set was converted to XML
416
                // Rebuild the version value from user format i.e the change set was converted to XML
416
                changeSet.rebuildWriteLockValueFromUserFormat(descriptor, session);
417
                changeSet.rebuildWriteLockValueFromUserFormat(descriptor, session);
417
            }
418
            }
418
            int difference = descriptor.getOptimisticLockingPolicy().getVersionDifference(changeSet.getInitialWriteLockValue(), original, changeSet.getPrimaryKeys(), session);
419
            int difference = descriptor.getOptimisticLockingPolicy().getVersionDifference(changeSet.getInitialWriteLockValue(), original, changeSet.getId(), session);
419
            
420
            
420
            // Should be = 0 if was a good update, otherwise was already refreshed, or a version change was lost.
421
            // Should be = 0 if was a good update, otherwise was already refreshed, or a version change was lost.
421
            if (difference < 0) {
422
            if (difference < 0) {
422
                // The current version is newer than the one on the remote system, was refreshed already, ignore change.
423
                // The current version is newer than the one on the remote system, was refreshed already, ignore change.
423
                session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "change_from_remote_server_older_than_current_version", changeSet.getClassName(), changeSet.getPrimaryKeys());
424
                session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "change_from_remote_server_older_than_current_version", changeSet.getClassName(), changeSet.getId());
424
                return original;
425
                return original;
425
            } else if (difference > 0) {
426
            } else if (difference > 0) {
426
                // If the current version is much older than the remote system, so invalidate the object as a change was missed.
427
                // If the current version is much older than the remote system, so invalidate the object as a change was missed.
427
                session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "current_version_much_older_than_change_from_remote_server", changeSet.getClassName(), changeSet.getPrimaryKeys());
428
                session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "current_version_much_older_than_change_from_remote_server", changeSet.getClassName(), changeSet.getId());
428
                session.getIdentityMapAccessorInstance().invalidateObject(changeSet.getPrimaryKeys(), localClassType);
429
                session.getIdentityMapAccessorInstance().invalidateObject(changeSet.getId(), localClassType);
429
                return original;
430
                return original;
430
            }
431
            }
431
        }
432
        }
432
433
433
        // Always merge into the original.
434
        // Always merge into the original.
434
        session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "Merging_from_remote_server", changeSet.getClassName(), changeSet.getPrimaryKeys());
435
        session.log(SessionLog.FINEST, SessionLog.PROPAGATION, "Merging_from_remote_server", changeSet.getClassName(), changeSet.getId());
435
436
436
        if (changeSet.isNew() || (changeSet.getSynchronizationType() != ClassDescriptor.DO_NOT_SEND_CHANGES)) {
437
        if (changeSet.isNew() || (changeSet.getSynchronizationType() != ClassDescriptor.DO_NOT_SEND_CHANGES)) {
437
            descriptor.getObjectBuilder().mergeChangesIntoObject(original, changeSet, null, this, false);
438
            descriptor.getObjectBuilder().mergeChangesIntoObject(original, changeSet, null, this, false);
438
            Vector primaryKey = changeSet.getPrimaryKeys();
439
            Object primaryKey = changeSet.getId();
439
440
440
            // PERF: Get the cached cache-key from the change-set.
441
            // PERF: Get the cached cache-key from the change-set.
441
            CacheKey cacheKey = changeSet.getActiveCacheKey();
442
            CacheKey cacheKey = changeSet.getActiveCacheKey();
Lines 535-545 Link Here
535
        }
536
        }
536
        //update the change policies with the refresh
537
        //update the change policies with the refresh
537
        descriptor.getObjectChangePolicy().revertChanges(clone, descriptor, (UnitOfWorkImpl)this.session, ((UnitOfWorkImpl)this.session).getCloneMapping());
538
        descriptor.getObjectChangePolicy().revertChanges(clone, descriptor, (UnitOfWorkImpl)this.session, ((UnitOfWorkImpl)this.session).getCloneMapping());
538
        Object primaryKey = this.session.keyFromObject(clone, descriptor);
539
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(clone, this.session, true);
540
        if (primaryKey == null) {
541
            return clone;
542
        }
543
        
539
        if (descriptor.usesOptimisticLocking()) {
544
        if (descriptor.usesOptimisticLocking()) {
540
            descriptor.getOptimisticLockingPolicy().mergeIntoParentCache((UnitOfWorkImpl)this.session, primaryKey, clone);
545
            descriptor.getOptimisticLockingPolicy().mergeIntoParentCache((UnitOfWorkImpl)this.session, primaryKey, clone);
541
        }
546
        }
542
543
        CacheKey parentCacheKey = ((UnitOfWorkImpl)this.session).getParent().getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, clone.getClass(), descriptor);
547
        CacheKey parentCacheKey = ((UnitOfWorkImpl)this.session).getParent().getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, clone.getClass(), descriptor);
544
        CacheKey uowCacheKey = this.session.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, clone.getClass(), descriptor);
548
        CacheKey uowCacheKey = this.session.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, clone.getClass(), descriptor);
545
549
Lines 593-599 Link Here
593
                    // lock it to prevent a reading thread from creating it as well
597
                    // lock it to prevent a reading thread from creating it as well
594
                    // there will be no deadlock situation because no other threads
598
                    // there will be no deadlock situation because no other threads
595
                    // will be able to reference this object.
599
                    // will be able to reference this object.
596
                    original = parent.getIdentityMapAccessorInstance().getWriteLockManager().appendLock(objectChangeSet.getPrimaryKeys(), original, descriptor, this, parent);
600
                    original = parent.getIdentityMapAccessorInstance().getWriteLockManager().appendLock(objectChangeSet.getId(), original, descriptor, this, parent);
597
                    objectBuilder.mergeIntoObject(original, true, clone, this, false, !descriptor.getCopyPolicy().buildsNewInstance());
601
                    objectBuilder.mergeIntoObject(original, true, clone, this, false, !descriptor.getCopyPolicy().buildsNewInstance());
598
                } else {
602
                } else {
599
                    objectBuilder.mergeChangesIntoObject(original, objectChangeSet, clone, this, !descriptor.getCopyPolicy().buildsNewInstance());
603
                    objectBuilder.mergeChangesIntoObject(original, objectChangeSet, clone, this, !descriptor.getCopyPolicy().buildsNewInstance());
Lines 611-617 Link Here
611
            } else {
615
            } else {
612
                // Invalidate any object that was marked invalid during the change calculation, even if it was new as multiple flushes 
616
                // Invalidate any object that was marked invalid during the change calculation, even if it was new as multiple flushes 
613
                // and custom SQL could still produce invalid new objects.
617
                // and custom SQL could still produce invalid new objects.
614
                if (objectChangeSet.shouldInvalidateObject(original, parent)) {
618
                if (objectChangeSet.shouldInvalidateObject(original, parent) && (!unitOfWork.isNestedUnitOfWork())) {
615
                    parent.getIdentityMapAccessor().invalidateObject(original);
619
                    parent.getIdentityMapAccessor().invalidateObject(original);
616
                    // no need to update cacheKey properties here
620
                    // no need to update cacheKey properties here
617
                }
621
                }
Lines 786-796 Link Here
786
    protected Object registerObjectForMergeCloneIntoWorkingCopy(Object clone) {
790
    protected Object registerObjectForMergeCloneIntoWorkingCopy(Object clone) {
787
        UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)this.session;
791
        UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)this.session;
788
        ClassDescriptor descriptor = unitOfWork.getDescriptor(clone.getClass());
792
        ClassDescriptor descriptor = unitOfWork.getDescriptor(clone.getClass());
789
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(clone, unitOfWork);
793
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(clone, unitOfWork, true);
790
794
791
        // Must use the java class as this may be a bean that we are merging and it may not have the same class as the
795
        // Must use the java class as this may be a bean that we are merging and it may not have the same class as the
792
        // objects in the cache.  As of EJB 2.0.
796
        // objects in the cache.  As of EJB 2.0.
793
        Object objectFromCache = unitOfWork.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, descriptor.getJavaClass(), false, descriptor);
797
        Object objectFromCache = null;
798
        if (primaryKey != null) {
799
            objectFromCache = unitOfWork.getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, descriptor.getJavaClass(), false, descriptor);
800
        }
794
        if (objectFromCache == null) {
801
        if (objectFromCache == null) {
795
            // Ensure we return the working copy if this has already been registered.
802
            // Ensure we return the working copy if this has already been registered.
796
            objectFromCache = unitOfWork.checkIfAlreadyRegistered(clone, descriptor);
803
            objectFromCache = unitOfWork.checkIfAlreadyRegistered(clone, descriptor);
Lines 801-869 Link Here
801
                if (shouldMergeCloneIntoWorkingCopy() || shouldMergeCloneWithReferencesIntoWorkingCopy()) {
808
                if (shouldMergeCloneIntoWorkingCopy() || shouldMergeCloneWithReferencesIntoWorkingCopy()) {
802
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("cannot_merge_removed_entity", new Object[] { clone }));
809
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("cannot_merge_removed_entity", new Object[] { clone }));
803
                }
810
                }
804
            }
811
            }            
805
            
806
            return objectFromCache;
812
            return objectFromCache;
807
        }
813
        }
808
814
809
        org.eclipse.persistence.queries.DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();
815
        DoesExistQuery existQuery = descriptor.getQueryManager().getDoesExistQuery();
810
        // Optimize cache option to avoid executing the does exist query.
816
        // Optimize cache option to avoid executing the does exist query.
811
        if (existQuery.shouldCheckCacheForDoesExist()) {
817
        if (existQuery.shouldCheckCacheForDoesExist()) {
812
            if (descriptor.usesVersionLocking()){
818
            checkNewObjectLockVersion(clone, primaryKey, descriptor, unitOfWork);
813
                VersionLockingPolicy policy = (VersionLockingPolicy)descriptor.getOptimisticLockingPolicy();
819
            Object registeredObject = unitOfWork.internalRegisterObject(clone, descriptor);            
814
                Object baseValue = policy.getBaseValue();
815
                Object objectLockValue = policy.getWriteLockValue(clone, primaryKey, unitOfWork);
816
                if ( policy.isNewerVersion(objectLockValue, baseValue) ) {
817
                    throw OptimisticLockException.objectChangedSinceLastMerge(clone);
818
                }
819
            }
820
            Object registeredObject = unitOfWork.internalRegisterObject(clone, descriptor);
821
            
822
            if (unitOfWork.hasNewObjects() && unitOfWork.getNewObjectsOriginalToClone().containsKey(clone)) {
820
            if (unitOfWork.hasNewObjects() && unitOfWork.getNewObjectsOriginalToClone().containsKey(clone)) {
823
                mergedNewObjects.put(registeredObject, registeredObject);
821
                this.mergedNewObjects.put(registeredObject, registeredObject);
824
            }
822
            }            
825
            
826
            return registeredObject;
823
            return registeredObject;
827
        }
824
        }
828
825
829
        // Check early return to check if it is a new object, i.e. null primary key.
826
        // Check early return to check if it is a new object, i.e. null primary key.
830
        Boolean doesExist = (Boolean)existQuery.checkEarlyReturn(clone, primaryKey, unitOfWork, null);
827
        Boolean doesExist = Boolean.FALSE;
828
        if (primaryKey != null) {
829
            doesExist = (Boolean)existQuery.checkEarlyReturn(clone, primaryKey, unitOfWork, null);
830
        }
831
        if (doesExist == Boolean.FALSE) {
831
        if (doesExist == Boolean.FALSE) {
832
            //bug272704: throw an exception if this object is new yet has a version set to avoid merging in deleted objects
832
            checkNewObjectLockVersion(clone, primaryKey, descriptor, unitOfWork);
833
            if (descriptor.usesVersionLocking()){
834
                VersionLockingPolicy policy = (VersionLockingPolicy)descriptor.getOptimisticLockingPolicy();
835
                Object baseValue = policy.getBaseValue();
836
                Object objectLockValue = policy.getWriteLockValue(clone, primaryKey, unitOfWork);
837
                if ( policy.isNewerVersion(objectLockValue, baseValue) ) {
838
                    throw OptimisticLockException.objectChangedSinceLastMerge(clone);
839
                }
840
            }
841
            Object registeredObject = unitOfWork.internalRegisterObject(clone, descriptor);
833
            Object registeredObject = unitOfWork.internalRegisterObject(clone, descriptor);
842
            mergedNewObjects.put(registeredObject, registeredObject);
834
            this.mergedNewObjects.put(registeredObject, registeredObject);
843
            return registeredObject;
835
            return registeredObject;
844
        }
836
        }
845
    
837
    
846
        // Otherwise it is existing and not in the cache so it must be read.
838
        // Otherwise it is existing and not in the cache so it must be read.
847
        Object object = unitOfWork.readObject(clone);
839
        Object object = unitOfWork.readObject(clone);
848
        if (object == null) {
840
        if (object == null) {
849
            //bug272704: throw an exception if this object is new yet has a version set to avoid merging in deleted objects
841
            checkNewObjectLockVersion(clone, primaryKey, descriptor, unitOfWork);
850
            if (descriptor.usesVersionLocking()){
851
                VersionLockingPolicy policy = (VersionLockingPolicy)descriptor.getOptimisticLockingPolicy();
852
                Object baseValue = policy.getBaseValue();
853
                Object objectLockValue = policy.getWriteLockValue(clone, primaryKey, unitOfWork);
854
                if ( policy.isNewerVersion(objectLockValue, baseValue) ) {
855
                    throw OptimisticLockException.objectChangedSinceLastMerge(clone);
856
                }
857
            }
858
            
859
            //bug6180972: avoid internal register's existence check and be sure to put the new object in the mergedNewObjects collection
842
            //bug6180972: avoid internal register's existence check and be sure to put the new object in the mergedNewObjects collection
860
            object =  unitOfWork.cloneAndRegisterNewObject(clone);
843
            object =  unitOfWork.cloneAndRegisterNewObject(clone);
861
            mergedNewObjects.put(object, object);
844
            this.mergedNewObjects.put(object, object);
862
        }
845
        }
863
        return object;
846
        return object;
864
    }
847
    }
865
848
866
    /**
849
    /**
850
     * Check if the new object's version has been set, if so, then it was an existing object that was deleted.
851
     * Raise an error instead of reincarnating the object.
852
     */
853
    public void checkNewObjectLockVersion(Object clone, Object primaryKey, ClassDescriptor descriptor, UnitOfWorkImpl unitOfWork) {
854
        //bug272704: throw an exception if this object is new yet has a version set to avoid merging in deleted objects
855
        if (descriptor.usesVersionLocking()){
856
            VersionLockingPolicy policy = (VersionLockingPolicy)descriptor.getOptimisticLockingPolicy();
857
            Object baseValue = policy.getBaseValue();
858
            Object objectLockValue = policy.getWriteLockValue(clone, primaryKey, unitOfWork);
859
            if (policy.isNewerVersion(objectLockValue, baseValue)) {
860
                throw OptimisticLockException.objectChangedSinceLastMerge(clone);
861
            }
862
        }
863
    }
864
    
865
    /**
867
     * Determine if the object is a registered new object, and that this is a nested unit of work
866
     * Determine if the object is a registered new object, and that this is a nested unit of work
868
     * merge into the parent.  In this case private mappings will register the object as being removed.
867
     * merge into the parent.  In this case private mappings will register the object as being removed.
869
     */
868
     */
Lines 915-922 Link Here
915
     * Used to set the object that the merge manager is waiting on, in order to acquire locks
914
     * Used to set the object that the merge manager is waiting on, in order to acquire locks
916
     * If this value is null then the merge manager is not waiting on any locks.
915
     * If this value is null then the merge manager is not waiting on any locks.
917
     */
916
     */
918
    public void setWriteLockQueued(CacheKey writeLockQueued) {
917
    public void setWriteLockQueued(Object primaryKey) {
919
        this.writeLockQueued = writeLockQueued;
918
        this.writeLockQueued = primaryKey;
920
    }
919
    }
921
920
922
    /**
921
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/ObjectChangeSet.java (-46 / +33 lines)
Lines 21-26 Link Here
21
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
21
import org.eclipse.persistence.descriptors.VersionLockingPolicy;
22
import org.eclipse.persistence.descriptors.TimestampLockingPolicy;
22
import org.eclipse.persistence.descriptors.TimestampLockingPolicy;
23
import org.eclipse.persistence.mappings.*;
23
import org.eclipse.persistence.mappings.*;
24
import org.eclipse.persistence.internal.identitymaps.CacheId;
24
import org.eclipse.persistence.internal.identitymaps.CacheKey;
25
import org.eclipse.persistence.internal.identitymaps.CacheKey;
25
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
26
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
26
27
Lines 38-44 Link Here
38
    protected List<org.eclipse.persistence.sessions.changesets.ChangeRecord> changes;
39
    protected List<org.eclipse.persistence.sessions.changesets.ChangeRecord> changes;
39
    protected transient Map<String, ChangeRecord> attributesToChanges;
40
    protected transient Map<String, ChangeRecord> attributesToChanges;
40
    protected boolean shouldBeDeleted;
41
    protected boolean shouldBeDeleted;
41
    protected CacheKey cacheKey;
42
    protected Object id;
42
    protected transient Class classType;
43
    protected transient Class classType;
43
    protected String className;
44
    protected String className;
44
    protected boolean isNew;
45
    protected boolean isNew;
Lines 97-105 Link Here
97
        this.cloneObject = cloneObject;
98
        this.cloneObject = cloneObject;
98
        this.isNew = isNew;
99
        this.isNew = isNew;
99
        this.shouldBeDeleted = false;
100
        this.shouldBeDeleted = false;
100
        if ((primaryKey != null) && !((Vector)primaryKey).contains(null)) {
101
        this.id = primaryKey;
101
            this.cacheKey = new CacheKey(primaryKey);
102
        }
103
        this.classType = descriptor.getJavaClass();
102
        this.classType = descriptor.getJavaClass();
104
        this.className = this.classType.getName();
103
        this.className = this.classType.getName();
105
        this.descriptor = descriptor;
104
        this.descriptor = descriptor;
Lines 192-206 Link Here
192
    /**
191
    /**
193
     * Ensure change sets with the same primary key are equal.
192
     * Ensure change sets with the same primary key are equal.
194
     */
193
     */
195
    public boolean equals(org.eclipse.persistence.sessions.changesets.ObjectChangeSet objectChange) {
194
    public boolean equals(ObjectChangeSet objectChange) {
196
        if (this == objectChange) {
195
        if (this == objectChange) {
197
            return true;
196
            return true;
198
        } else if (getCacheKey() == null) {
197
        } else if (this.id == null) {
199
            //new objects are compared based on identity
198
            //new objects are compared based on identity
200
            return false;
199
            return false;
201
        }
200
        }
202
201
203
        return (getCacheKey().equals(((ObjectChangeSet)objectChange).getCacheKey()));
202
        return (this.id.equals(objectChange.id));
204
    }
203
    }
205
204
206
    /**
205
    /**
Lines 223-237 Link Here
223
    }
222
    }
224
223
225
    /**
224
    /**
226
     * Return the CacheKey for the object that this is a change set for.
227
     */
228
    public CacheKey getCacheKey() {
229
        // this must not be lazy initialized as newness of the ObjectChangeSet and
230
        //equality are determined by the existence of a cachekey - GY
231
        return cacheKey;
232
    }
233
234
    /**
235
     * ADVANCED:
225
     * ADVANCED:
236
     * This method will return a collection of the attributes changed in the object.
226
     * This method will return a collection of the attributes changed in the object.
237
     */
227
     */
Lines 313-324 Link Here
313
     * ADVANCED:
303
     * ADVANCED:
314
     * This method returns the primary keys for the object that this change set represents.
304
     * This method returns the primary keys for the object that this change set represents.
315
     */
305
     */
306
    @Deprecated
316
    public Vector getPrimaryKeys() {
307
    public Vector getPrimaryKeys() {
317
        if (getCacheKey() == null) {
308
        if (this.id instanceof CacheId) {
318
            return null;
309
            return new Vector(Arrays.asList(((CacheId)this.id).getPrimaryKey()));
319
        }
310
        }
320
        return getCacheKey().getKey();
311
        Vector primaryKey = new Vector(1);
312
        primaryKey.add(this.id);
313
        return primaryKey;
321
    }
314
    }
315
    
316
    /**
317
     * ADVANCED:
318
     * This method returns the primary key for the object that this change set represents.
319
     */
320
    public Object getId() {
321
        return this.id;
322
    }
322
323
323
    public int getSynchronizationType() {
324
    public int getSynchronizationType() {
324
        return cacheSynchronizationType;
325
        return cacheSynchronizationType;
Lines 362-368 Link Here
362
                }
363
                }
363
            } else {
364
            } else {
364
                // It is not a unitOfWork so we must be merging into a distributed cache.
365
                // It is not a unitOfWork so we must be merging into a distributed cache.
365
                attributeValue = session.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(getPrimaryKeys(), getClassType(session), descriptor);
366
                attributeValue = session.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(getId(), getClassType(session), descriptor);
366
            }
367
            }
367
        
368
        
368
            if ((attributeValue == null) && (shouldRead)) {
369
            if ((attributeValue == null) && (shouldRead)) {
Lines 371-377 Link Here
371
                ReadObjectQuery query = new ReadObjectQuery();
372
                ReadObjectQuery query = new ReadObjectQuery();
372
                query.setShouldUseWrapperPolicy(false);
373
                query.setShouldUseWrapperPolicy(false);
373
                query.setReferenceClass(getClassType(session));
374
                query.setReferenceClass(getClassType(session));
374
                query.setSelectionId(getPrimaryKeys());
375
                query.setSelectionId(getId());
375
                attributeValue = session.executeQuery(query);
376
                attributeValue = session.executeQuery(query);
376
            }
377
            }
377
        }
378
        }
Lines 502-512 Link Here
502
     * cache key, otherwise return the identity hashcode of this object.
503
     * cache key, otherwise return the identity hashcode of this object.
503
     */
504
     */
504
    public int hashCode() {
505
    public int hashCode() {
505
        if (getCacheKey() == null) {
506
        if (getId() == null) {
506
            //new objects are compared based on identity
507
            //new objects are compared based on identity
507
            return System.identityHashCode(this);
508
            return System.identityHashCode(this);
508
        }
509
        }
509
        return getCacheKey().hashCode();
510
        return getId().hashCode();
510
    }
511
    }
511
512
512
    /**
513
    /**
Lines 632-638 Link Here
632
     */
633
     */
633
    public void readIdentityInformation(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException {
634
    public void readIdentityInformation(java.io.ObjectInputStream stream) throws java.io.IOException, ClassNotFoundException {
634
        // bug 3526981 - avoid side effects of setter methods by directly assigning variables
635
        // bug 3526981 - avoid side effects of setter methods by directly assigning variables
635
        this.cacheKey = (CacheKey)stream.readObject();
636
        this.id = stream.readObject();
636
        this.className = (String)stream.readObject();
637
        this.className = (String)stream.readObject();
637
        this.writeLockValue = stream.readObject();
638
        this.writeLockValue = stream.readObject();
638
        this.initialWriteLockValue = stream.readObject();
639
        this.initialWriteLockValue = stream.readObject();
Lines 663-672 Link Here
663
    }
664
    }
664
665
665
    /**
666
    /**
666
     * Set the cache key.
667
     * Set the id of the object for this change set.
667
     */
668
     */
668
    public void setCacheKey(CacheKey cacheKey) {
669
    public void setId(Object id) {
669
        this.cacheKey = cacheKey;
670
        this.id = id;
670
    }
671
    }
671
672
672
    /**
673
    /**
Lines 759-765 Link Here
759
        // ignore optimistic locking policy if it can't compare lock values (like FieldsLockingPolicy).
760
        // ignore optimistic locking policy if it can't compare lock values (like FieldsLockingPolicy).
760
        if(optimisticLockingPolicy.supportsWriteLockValuesComparison()) {
761
        if(optimisticLockingPolicy.supportsWriteLockValuesComparison()) {
761
            this.optimisticLockingPolicy = optimisticLockingPolicy;
762
            this.optimisticLockingPolicy = optimisticLockingPolicy;
762
            this.initialWriteLockValue = optimisticLockingPolicy.getWriteLockValue(cloneObject, getPrimaryKeys(), session);
763
            this.initialWriteLockValue = optimisticLockingPolicy.getWriteLockValue(cloneObject, getId(), session);
763
        }
764
        }
764
    }
765
    }
765
766
Lines 783-789 Link Here
783
     * This method is used to set the initial writeLock value for an ObjectChangeSet.
784
     * This method is used to set the initial writeLock value for an ObjectChangeSet.
784
     * The initial value will only be set once, and can not be overwritten.
785
     * The initial value will only be set once, and can not be overwritten.
785
     */
786
     */
786
    public void setInitialWriteLockValue(java.lang.Object initialWriteLockValue) {
787
    public void setInitialWriteLockValue(Object initialWriteLockValue) {
787
        if (this.initialWriteLockValue == null) {
788
        if (this.initialWriteLockValue == null) {
788
            this.initialWriteLockValue = initialWriteLockValue;
789
            this.initialWriteLockValue = initialWriteLockValue;
789
        }
790
        }
Lines 891-897 Link Here
891
     * ObjectChangeSet to the stream
892
     * ObjectChangeSet to the stream
892
     */
893
     */
893
    public void writeIdentityInformation(java.io.ObjectOutputStream stream) throws java.io.IOException {
894
    public void writeIdentityInformation(java.io.ObjectOutputStream stream) throws java.io.IOException {
894
        stream.writeObject(this.cacheKey);
895
        stream.writeObject(this.id);
895
        stream.writeObject(this.className);
896
        stream.writeObject(this.className);
896
        stream.writeObject(this.writeLockValue);
897
        stream.writeObject(this.writeLockValue);
897
        stream.writeObject(this.initialWriteLockValue);
898
        stream.writeObject(this.initialWriteLockValue);
Lines 921-940 Link Here
921
    }
922
    }
922
923
923
    /**
924
    /**
924
     * INTERNAL:
925
     */
926
    public void setPrimaryKeys(Vector key) {
927
        if (key == null) {
928
            return;
929
        }
930
        if (getCacheKey() == null) {
931
            setCacheKey(new CacheKey(key));
932
        } else {
933
            getCacheKey().setKey(key);
934
        }
935
    }
936
937
    /**
938
     * This set contains the list of attributes that must be calculated at commit time.
925
     * This set contains the list of attributes that must be calculated at commit time.
939
     */
926
     */
940
    public Set<String> getDeferredSet() {
927
    public Set<String> getDeferredSet() {
Lines 999-1005 Link Here
999
     * Remove object represent this change set from identity map.  If change set is in XML format, rebuild pk to the correct class type from String
986
     * Remove object represent this change set from identity map.  If change set is in XML format, rebuild pk to the correct class type from String
1000
     */
987
     */
1001
    protected void removeFromIdentityMap(AbstractSession session) {
988
    protected void removeFromIdentityMap(AbstractSession session) {
1002
        session.getIdentityMapAccessor().removeFromIdentityMap(getPrimaryKeys(), getClassType(session));
989
        session.getIdentityMapAccessor().removeFromIdentityMap(getId(), getClassType(session));
1003
    }
990
    }
1004
991
1005
    /**
992
    /**
Lines 1026-1032 Link Here
1026
            return true;
1013
            return true;
1027
        }
1014
        }
1028
        
1015
        
1029
        Object originalWriteLockValue = optimisticLockingPolicy.getWriteLockValue(original, getPrimaryKeys(), session);
1016
        Object originalWriteLockValue = optimisticLockingPolicy.getWriteLockValue(original, getId(), session);
1030
        
1017
        
1031
        // initialWriteLockValue and originalWriteLockValue are not equal.
1018
        // initialWriteLockValue and originalWriteLockValue are not equal.
1032
        // Example: 
1019
        // Example: 
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/remote/RemoteValueHolder.java (-2 / +1 lines)
Lines 14-20 Link Here
14
14
15
import java.rmi.server.ObjID;
15
import java.rmi.server.ObjID;
16
import java.io.*;
16
import java.io.*;
17
import java.util.*;
18
import org.eclipse.persistence.sessions.remote.*;
17
import org.eclipse.persistence.sessions.remote.*;
19
import org.eclipse.persistence.queries.*;
18
import org.eclipse.persistence.queries.*;
20
import org.eclipse.persistence.descriptors.ClassDescriptor;
19
import org.eclipse.persistence.descriptors.ClassDescriptor;
Lines 57-63 Link Here
57
            return false;
56
            return false;
58
        }
57
        }
59
58
60
        return (getTargetObjectPrimaryKeys() != null) && (!((Vector)getTargetObjectPrimaryKeys()).isEmpty()) && getMapping().isOneToOneMapping() && (!getQuery().shouldRefreshIdentityMapResult()) && (!getQuery().shouldRefreshRemoteIdentityMapResult()) && (getQuery().shouldMaintainCache());
59
        return (getTargetObjectPrimaryKeys() != null) && getMapping().isOneToOneMapping() && (!getQuery().shouldRefreshIdentityMapResult()) && (!getQuery().shouldRefreshRemoteIdentityMapResult()) && (getQuery().shouldMaintainCache());
61
    }
60
    }
62
61
63
    /**
62
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkChangeSet.java (-6 / +6 lines)
Lines 16-22 Link Here
16
import java.io.*;
16
import java.io.*;
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.internal.helper.CustomObjectInputStream;
18
import org.eclipse.persistence.internal.helper.CustomObjectInputStream;
19
import org.eclipse.persistence.internal.identitymaps.CacheKey;
20
19
21
/**
20
/**
22
 * <p>
21
 * <p>
Lines 170-176 Link Here
170
                        getAllChangeSets().put(objectChanges, objectChanges);
169
                        getAllChangeSets().put(objectChanges, objectChanges);
171
                    }
170
                    }
172
         
171
         
173
                    if (objectChanges.getCacheKey() != null) {
172
                    if (objectChanges.getId() != null) {
174
                        Map<ObjectChangeSet, ObjectChangeSet> map = getObjectChanges().get(objectChanges.getClassType());
173
                        Map<ObjectChangeSet, ObjectChangeSet> map = getObjectChanges().get(objectChanges.getClassType());
175
174
176
                        if (map == null) {
175
                        if (map == null) {
Lines 235-241 Link Here
235
        }
234
        }
236
        ObjectChangeSet localChangeSet = this.findObjectChangeSet(tofind, mergeFromChangeSet);
235
        ObjectChangeSet localChangeSet = this.findObjectChangeSet(tofind, mergeFromChangeSet);
237
        if (localChangeSet == null) {//not found locally then replace it with the one from the merging changeset
236
        if (localChangeSet == null) {//not found locally then replace it with the one from the merging changeset
238
            localChangeSet = new ObjectChangeSet(tofind.getPrimaryKeys(), tofind.getDescriptor(), tofind.getUnitOfWorkClone(), this, tofind.isNew());
237
            localChangeSet = new ObjectChangeSet(tofind.getId(), tofind.getDescriptor(), tofind.getUnitOfWorkClone(), this, tofind.isNew());
239
            this.addObjectChangeSetForIdentity(localChangeSet, localChangeSet.getUnitOfWorkClone());
238
            this.addObjectChangeSetForIdentity(localChangeSet, localChangeSet.getUnitOfWorkClone());
240
        }
239
        }
241
        return localChangeSet;
240
        return localChangeSet;
Lines 520-529 Link Here
520
     */
519
     */
521
    public void putNewObjectInChangesList(ObjectChangeSet objectChangeSet, AbstractSession session) {
520
    public void putNewObjectInChangesList(ObjectChangeSet objectChangeSet, AbstractSession session) {
522
        // Must reset the cache key for new objects assigned in insert.
521
        // Must reset the cache key for new objects assigned in insert.
523
        if (objectChangeSet.getCacheKey() == null) {
522
        if (objectChangeSet.getId() == null) {
524
            objectChangeSet.setCacheKey(new CacheKey(session.getDescriptor(objectChangeSet.getUnitOfWorkClone().getClass()).getObjectBuilder().extractPrimaryKeyFromObject(objectChangeSet.getUnitOfWorkClone(), session, false)));
523
            Object clone = objectChangeSet.getUnitOfWorkClone();
524
            objectChangeSet.setId(session.getDescriptor(clone.getClass()).getObjectBuilder().extractPrimaryKeyFromObject(clone, session, false));
525
        }
525
        }
526
        this.addObjectChangeSet(objectChangeSet, session, false);
526
        addObjectChangeSet(objectChangeSet, session, false);
527
        removeObjectChangeSetFromNewList(objectChangeSet, session);
527
        removeObjectChangeSetFromNewList(objectChangeSet, session);
528
    }
528
    }
529
529
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java (-44 / +65 lines)
Lines 31-36 Link Here
31
import java.io.*;
31
import java.io.*;
32
32
33
import org.eclipse.persistence.internal.helper.*;
33
import org.eclipse.persistence.internal.helper.*;
34
import org.eclipse.persistence.annotations.CacheKeyType;
34
import org.eclipse.persistence.descriptors.*;
35
import org.eclipse.persistence.descriptors.*;
35
import org.eclipse.persistence.internal.descriptors.*;
36
import org.eclipse.persistence.internal.descriptors.*;
36
import org.eclipse.persistence.internal.descriptors.DescriptorIterator.CascadeCondition;
37
import org.eclipse.persistence.internal.descriptors.DescriptorIterator.CascadeCondition;
Lines 400-408 Link Here
400
401
401
        // Also mark all subclasses as read-only.
402
        // Also mark all subclasses as read-only.
402
        if (descriptor.hasInheritance()) {
403
        if (descriptor.hasInheritance()) {
403
            for (Enumeration childEnum = descriptor.getInheritancePolicy().getChildDescriptors().elements();
404
            for (ClassDescriptor childDescriptor : descriptor.getInheritancePolicy().getChildDescriptors()) {
404
                     childEnum.hasMoreElements();) {
405
                ClassDescriptor childDescriptor = (ClassDescriptor)childEnum.nextElement();
406
                addReadOnlyClass(childDescriptor.getJavaClass());
405
                addReadOnlyClass(childDescriptor.getJavaClass());
407
            }
406
            }
408
        }
407
        }
Lines 894-900 Link Here
894
     * The unit of work cache key is passed to the normal cloneAndRegisterObject method.
893
     * The unit of work cache key is passed to the normal cloneAndRegisterObject method.
895
     */
894
     */
896
    public Object cloneAndRegisterObject(Object original, CacheKey parentCacheKey, ClassDescriptor descriptor) {
895
    public Object cloneAndRegisterObject(Object original, CacheKey parentCacheKey, ClassDescriptor descriptor) {
897
        CacheKey unitOfWorkCacheKey = getIdentityMapAccessorInstance().acquireLock(parentCacheKey.getKey(), original.getClass(), descriptor);
896
        CacheKey unitOfWorkCacheKey = null;
897
        if (parentCacheKey.getKey() == null) {
898
            // The primary key may be null for nested units of work with new parent objects.
899
            unitOfWorkCacheKey = new UnitOfWorkCacheKey(null);
900
            unitOfWorkCacheKey.acquire();
901
        } else {
902
            unitOfWorkCacheKey = getIdentityMapAccessorInstance().acquireLock(parentCacheKey.getKey(), original.getClass(), descriptor);
903
        }
898
        try {
904
        try {
899
            return cloneAndRegisterObject(original, parentCacheKey, unitOfWorkCacheKey, descriptor);
905
            return cloneAndRegisterObject(original, parentCacheKey, unitOfWorkCacheKey, descriptor);
900
        } finally {
906
        } finally {
Lines 971-977 Link Here
971
            workingClone = builder.instantiateWorkingCopyClone(original, this);
977
            workingClone = builder.instantiateWorkingCopyClone(original, this);
972
            // PERF: Cache the primary key if implements PersistenceEntity.
978
            // PERF: Cache the primary key if implements PersistenceEntity.
973
            if (workingClone instanceof PersistenceEntity) {
979
            if (workingClone instanceof PersistenceEntity) {
974
                ((PersistenceEntity)workingClone)._persistence_setPKVector(parentCacheKey.getKey());
980
                ((PersistenceEntity)workingClone)._persistence_setId(parentCacheKey.getKey());
975
            }
981
            }
976
982
977
            // This must be registered before it is built to avoid really obscure cycles.
983
            // This must be registered before it is built to avoid really obscure cycles.
Lines 2375-2383 Link Here
2375
                 newObjectsEnum.hasNext();) {
2381
                 newObjectsEnum.hasNext();) {
2376
            Object object = newObjectsEnum.next();
2382
            Object object = newObjectsEnum.next();
2377
            if (theClass.isInstance(object)) {
2383
            if (theClass.isInstance(object)) {
2378
                // removed dead null check as this method is never called if selectionKey == null
2384
                Object primaryKey = objectBuilder.extractPrimaryKeyFromObject(object, this, true);
2379
                Object primaryKey = objectBuilder.extractPrimaryKeyFromObject(object, this);
2385
                if ((primaryKey != null) && primaryKey.equals(selectionKey)) {
2380
                if (new CacheKey(primaryKey).equals(new CacheKey(selectionKey))) {
2381
                    return object;
2386
                    return object;
2382
                }
2387
                }
2383
            }
2388
            }
Lines 2395-2403 Link Here
2395
        if (!hasNewObjects()) {
2400
        if (!hasNewObjects()) {
2396
            return null;
2401
            return null;
2397
        }
2402
        }
2398
        for (Iterator newObjectsEnum = getNewObjectsCloneToOriginal().keySet().iterator();
2403
        for (Object object : getNewObjectsCloneToOriginal().keySet()) {
2399
                 newObjectsEnum.hasNext();) {
2400
            Object object = newObjectsEnum.next();
2401
            if (theClass.isInstance(object)) {
2404
            if (theClass.isInstance(object)) {
2402
                if (selectionCriteria == null) {
2405
                if (selectionCriteria == null) {
2403
                    return object;
2406
                    return object;
Lines 2617-2635 Link Here
2617
     */
2620
     */
2618
    protected Object getObjectFromSharedCacheForMerge(Object implementation, ObjectBuilder builder, ClassDescriptor descriptor){
2621
    protected Object getObjectFromSharedCacheForMerge(Object implementation, ObjectBuilder builder, ClassDescriptor descriptor){
2619
        Object original = null;
2622
        Object original = null;
2620
        Object primaryKey = builder.extractPrimaryKeyFromObject(implementation, this);
2623
        Object primaryKey = builder.extractPrimaryKeyFromObject(implementation, this, true);
2621
        if (this.lastUsedMergeManager == null){
2624
        if (this.lastUsedMergeManager == null) {
2622
            // not merging into the shared cache so just return object from parent identity map
2625
            // not merging into the shared cache so just return object from parent identity map
2626
            // If a nested unit of work, new objects may have null primary keys, and not be in the cache.
2627
            if (primaryKey == null) {
2628
                return null;
2629
            }
2623
            return getParent().getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, implementation.getClass(), descriptor);
2630
            return getParent().getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, implementation.getClass(), descriptor);
2624
        }
2631
        }
2625
        CacheKey cacheKey = getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, implementation.getClass(), descriptor);
2632
        CacheKey cacheKey = getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, implementation.getClass(), descriptor);
2626
        if (cacheKey != null){
2633
        if (cacheKey != null) {
2627
            if ( cacheKey.acquireReadLockNoWait()){
2634
            if (cacheKey.acquireReadLockNoWait()) {
2628
                original = cacheKey.getObject();
2635
                original = cacheKey.getObject();
2629
                cacheKey.releaseReadLock();
2636
                cacheKey.releaseReadLock();
2630
            }else{
2637
            } else {
2631
                if (!getMergeManager().isTransitionedToDeferredLocks())
2638
                if (!getMergeManager().isTransitionedToDeferredLocks()) {
2632
                getParent().getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(getMergeManager());
2639
                    getParent().getIdentityMapAccessorInstance().getWriteLockManager().transitionToDeferredLocks(getMergeManager());
2640
                }
2633
                cacheKey.acquireDeferredLock();
2641
                cacheKey.acquireDeferredLock();
2634
                original = cacheKey.getObject();
2642
                original = cacheKey.getObject();
2635
                if (original == null) {
2643
                if (original == null) {
Lines 3662-3672 Link Here
3662
            Map deletedObjects = this.unitOfWorkChangeSet.getDeletedObjects();
3670
            Map deletedObjects = this.unitOfWorkChangeSet.getDeletedObjects();
3663
            for (Iterator removedObjects = deletedObjects.keySet().iterator(); removedObjects.hasNext(); ) {
3671
            for (Iterator removedObjects = deletedObjects.keySet().iterator(); removedObjects.hasNext(); ) {
3664
                ObjectChangeSet removedObjectChangeSet = (ObjectChangeSet) removedObjects.next();
3672
                ObjectChangeSet removedObjectChangeSet = (ObjectChangeSet) removedObjects.next();
3665
                Vector primaryKeys = removedObjectChangeSet.getPrimaryKeys();
3673
                Object primaryKey = removedObjectChangeSet.getId();
3666
                ClassDescriptor descriptor = removedObjectChangeSet.getDescriptor();
3674
                ClassDescriptor descriptor = removedObjectChangeSet.getDescriptor();
3667
                // PERF: Do not remove if uow is isolated.
3675
                // PERF: Do not remove if uow is isolated.
3668
                if (!descriptor.shouldIsolateObjectsInUnitOfWork()) {
3676
                if (!descriptor.shouldIsolateObjectsInUnitOfWork()) {
3669
                    this.parent.getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKeys, descriptor.getJavaClass(), descriptor, removedObjectChangeSet.getUnitOfWorkClone());
3677
                    this.parent.getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKey, descriptor.getJavaClass(), descriptor, removedObjectChangeSet.getUnitOfWorkClone());
3670
                }
3678
                }
3671
            }
3679
            }
3672
        }
3680
        }
Lines 3885-3893 Link Here
3885
            if (registeredObject == null) {
3893
            if (registeredObject == null) {
3886
                // Check if object is existing, if it is it must be cloned into the unit of work
3894
                // Check if object is existing, if it is it must be cloned into the unit of work
3887
                // otherwise it is a new object
3895
                // otherwise it is a new object
3888
                Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(objectToRegister, this);
3896
                Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(objectToRegister, this, true);
3889
                // Always check the cache first.
3897
                // The primary key may be null for a new object in a nested unit of work (is existing in nested, new in parent).
3890
                registeredObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, objectToRegister.getClass(), descriptor);
3898
                if (primaryKey != null) {
3899
                    // Always check the cache first.
3900
                    registeredObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, objectToRegister.getClass(), descriptor);
3901
                }
3891
                if (registeredObject == null) {
3902
                if (registeredObject == null) {
3892
                    // This is a case where the object is not in the session cache,
3903
                    // This is a case where the object is not in the session cache,
3893
                    // so a new cache-key is used as there is no original to use for locking.
3904
                    // so a new cache-key is used as there is no original to use for locking.
Lines 5274-5283 Link Here
5274
                }
5285
                }
5275
                
5286
                
5276
                // Check if object exists in the IM.
5287
                // Check if object exists in the IM.
5277
                Object primaryKey = getCurrentDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, UnitOfWorkImpl.this);
5288
                Object primaryKey = getCurrentDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, UnitOfWorkImpl.this, true);
5278
5289
                if (primaryKey != null) {
5279
                // If object exists in IM remove it from the IM and also from clone mapping.
5290
                    // If object exists in IM remove it from the IM and also from clone mapping.
5280
                getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKey, object.getClass(), getCurrentDescriptor(), object);
5291
                    getIdentityMapAccessorInstance().removeFromIdentityMap(primaryKey, object.getClass(), getCurrentDescriptor(), object);
5292
                }
5281
                getCloneMapping().remove(object);
5293
                getCloneMapping().remove(object);
5282
                
5294
                
5283
                //remove from deleted objects.
5295
                //remove from deleted objects.
Lines 5794-5836 Link Here
5794
     * The instance will be lazy when it does not exist in the cache, and supports fetch groups.
5806
     * The instance will be lazy when it does not exist in the cache, and supports fetch groups.
5795
     * @param primaryKey - The primary key of the object, either as a List, singleton, IdClass or an instance of the object.
5807
     * @param primaryKey - The primary key of the object, either as a List, singleton, IdClass or an instance of the object.
5796
     */
5808
     */
5797
    public Object getReference(Class theClass, Object primaryKey) {
5809
    public Object getReference(Class theClass, Object id) {
5798
        ClassDescriptor descriptor = getDescriptor(theClass);
5810
        ClassDescriptor descriptor = getDescriptor(theClass);
5799
        if (descriptor == null || descriptor.isDescriptorTypeAggregate()) {
5811
        if (descriptor == null || descriptor.isDescriptorTypeAggregate()) {
5800
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unknown_bean_class", new Object[] { theClass }));
5812
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unknown_bean_class", new Object[] { theClass }));
5801
        }
5813
        }
5802
        Object reference;
5814
        Object reference;
5803
        if (primaryKey == null) { //gf721 - check for null PK
5815
        if (id == null) { //gf721 - check for null PK
5804
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
5816
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
5805
        }
5817
        }
5806
        Object primaryKeyValues;
5818
        Object primaryKey;
5807
        if (primaryKey instanceof List) {
5819
        if (id instanceof List) {
5808
            primaryKeyValues = new NonSynchronizedVector((List)primaryKey);
5820
            if (descriptor.getCacheKeyType() == CacheKeyType.ID_VALUE) {
5821
                if (((List)id).isEmpty()) {
5822
                    primaryKey = null;
5823
                } else {
5824
                    primaryKey = ((List)id).get(0);
5825
                }
5826
            } else {
5827
                primaryKey = new CacheId(((List)id).toArray());
5828
            }
5829
        } else if (id instanceof CacheId) {
5830
            primaryKey = id;
5809
        } else {
5831
        } else {
5810
            if (descriptor.getCMPPolicy() != null) {
5832
            if (descriptor.getCMPPolicy() != null) {
5811
                if (descriptor.getCMPPolicy().getPKClass() != null && !descriptor.getCMPPolicy().getPKClass().isAssignableFrom(primaryKey.getClass())) {
5833
                if (descriptor.getCMPPolicy().getPKClass() != null && !descriptor.getCMPPolicy().getPKClass().isAssignableFrom(id.getClass())) {
5812
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), primaryKey.getClass() }));
5834
                    throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), id.getClass() }));
5813
                }
5835
                }
5814
                primaryKeyValues = descriptor.getCMPPolicy().createPkVectorFromKey(primaryKey, this);
5836
                primaryKey = descriptor.getCMPPolicy().createPrimaryKeyFromId(id, this);
5815
            } else {
5837
            } else {
5816
                if (!primaryKey.getClass().equals(theClass)) {
5838
                if (!id.getClass().equals(theClass)) {
5817
                    primaryKeyValues = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(primaryKey, this);
5839
                    primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(id, this);
5818
                } else {
5840
                } else {
5819
                    primaryKeyValues = new NonSynchronizedVector(1);
5841
                    primaryKey = id;
5820
                    ((Vector)primaryKeyValues).add(primaryKey);
5821
                }
5842
                }
5822
            }
5843
            }
5823
        }
5844
        }
5824
        // If the class supports fetch groups then return a un-fetched instance.
5845
        // If the class supports fetch groups then return a un-fetched instance.
5825
        if (ClassConstants.FetchGroupTracker_class.isAssignableFrom(theClass)) {
5846
        if (ClassConstants.FetchGroupTracker_class.isAssignableFrom(theClass)) {
5826
            reference = getIdentityMapAccessor().getFromIdentityMap(primaryKeyValues, theClass);
5847
            reference = getIdentityMapAccessor().getFromIdentityMap(primaryKey, theClass);
5827
            if (reference == null) {
5848
            if (reference == null) {
5828
                if (primaryKey instanceof List) {
5849
                if ((id instanceof List) || (id instanceof CacheId) || (descriptor.getCMPPolicy() != null)) {
5829
                    AbstractRecord row = descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(primaryKeyValues, this);
5850
                    AbstractRecord row = descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(primaryKey, this);
5830
                    reference = descriptor.getObjectBuilder().buildNewInstance();
5851
                    reference = descriptor.getObjectBuilder().buildNewInstance();
5831
                    descriptor.getObjectBuilder().buildPrimaryKeyAttributesIntoObject(reference, row, new ReadObjectQuery(), this);
5852
                    descriptor.getObjectBuilder().buildPrimaryKeyAttributesIntoObject(reference, row, new ReadObjectQuery(), this);
5832
                } else {
5853
                } else {
5833
                    reference = descriptor.getCMPPolicy().createBeanUsingKey(primaryKey, this);
5854
                    reference = descriptor.getCMPPolicy().createBeanUsingKey(id, this);
5834
                }
5855
                }
5835
                ((FetchGroupTracker)reference)._persistence_setSession(this);
5856
                ((FetchGroupTracker)reference)._persistence_setSession(this);
5836
                FetchGroup fetchGroup = new FetchGroup();
5857
                FetchGroup fetchGroup = new FetchGroup();
Lines 5842-5848 Link Here
5842
            }
5863
            }
5843
        } else {
5864
        } else {
5844
            ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass());
5865
            ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass());
5845
            query.setSelectionId(primaryKeyValues);
5866
            query.setSelectionId(primaryKey);
5846
            query.conformResultsInUnitOfWork();
5867
            query.conformResultsInUnitOfWork();
5847
            query.setIsExecutionClone(true);
5868
            query.setIsExecutionClone(true);
5848
            reference = executeQuery(query);
5869
            reference = executeQuery(query);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/AggregateCollectionMapping.java (-64 / +59 lines)
Lines 539-556 Link Here
539
            shouldRepairOrder = ((IndirectList)currentList).isListOrderBrokenInDb();
539
            shouldRepairOrder = ((IndirectList)currentList).isListOrderBrokenInDb();
540
        }
540
        }
541
        
541
        
542
        HashMap<CacheKey, Object[]> previousAndCurrentByKey = new HashMap<CacheKey, Object[]>();
542
        HashMap<Object, Object[]> previousAndCurrentByKey = new HashMap<Object, Object[]>();
543
        int pkSize = getReferenceDescriptor().getPrimaryKeyFields().size();
543
        int pkSize = getReferenceDescriptor().getPrimaryKeyFields().size();
544
        
544
        
545
        // First index the current objects by their primary key.
545
        // First index the current objects by their primary key.
546
        for(int i=0; i < currentList.size(); i++) {
546
        for (int i=0; i < currentList.size(); i++) {
547
            Object currentObject = currentList.get(i);
547
            Object currentObject = currentList.get(i);
548
            try {
548
            try {
549
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
549
                CacheId primaryKey = (CacheId)getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
550
                ((Vector)primaryKey).add(i);
550
                primaryKey.add(i);
551
                CacheKey key = new CacheKey(primaryKey);
552
                Object[] previousAndCurrent = new Object[]{null, currentObject};
551
                Object[] previousAndCurrent = new Object[]{null, currentObject};
553
                previousAndCurrentByKey.put(key, previousAndCurrent);
552
                previousAndCurrentByKey.put(primaryKey, previousAndCurrent);
554
            } catch (NullPointerException e) {
553
            } catch (NullPointerException e) {
555
                // For CR#2646 quietly discard nulls added to a collection mapping.
554
                // For CR#2646 quietly discard nulls added to a collection mapping.
556
                // This try-catch is essentially a null check on currentObject, for
555
                // This try-catch is essentially a null check on currentObject, for
Lines 561-577 Link Here
561
            }
560
            }
562
        }
561
        }
563
562
564
        if(shouldRepairOrder) {
563
        if (shouldRepairOrder) {
565
            ((DeleteAllQuery)getDeleteAllQuery()).executeDeleteAll(query.getSession().getSessionForClass(getReferenceClass()), query.getTranslationRow(), new Vector(previousList));
564
            ((DeleteAllQuery)getDeleteAllQuery()).executeDeleteAll(query.getSession().getSessionForClass(getReferenceClass()), query.getTranslationRow(), new Vector(previousList));
566
        } else {
565
        } else {
567
            // Next index the previous objects (read from db or from backup in uow)
566
            // Next index the previous objects (read from db or from backup in uow)
568
            for(int i=0; i < previousList.size(); i++) {
567
            for(int i=0; i < previousList.size(); i++) {
569
                Object previousObject = previousList.get(i);
568
                Object previousObject = previousList.get(i);
570
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
569
                CacheId primaryKey = (CacheId)getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
571
                ((Vector)primaryKey).add(i);
570
                primaryKey.add(i);
572
                CacheKey key = new CacheKey(primaryKey);
571
                Object[] previousAndCurrent = previousAndCurrentByKey.get(primaryKey);
573
                Object[] previousAndCurrent = previousAndCurrentByKey.get(key);
572
                if (previousAndCurrent == null) {
574
                if(previousAndCurrent == null) {
575
                    // there's no current object - that means that previous object should be deleted
573
                    // there's no current object - that means that previous object should be deleted
576
                    DatabaseRecord extraData = new DatabaseRecord(1);
574
                    DatabaseRecord extraData = new DatabaseRecord(1);
577
                    extraData.put(this.listOrderField, i);
575
                    extraData.put(this.listOrderField, i);
Lines 582-591 Link Here
582
            }
580
            }
583
        }
581
        }
584
582
585
        Iterator<Map.Entry<CacheKey, Object[]>> it = previousAndCurrentByKey.entrySet().iterator();
583
        Iterator<Map.Entry<Object, Object[]>> it = previousAndCurrentByKey.entrySet().iterator();
586
        while(it.hasNext()) {
584
        while(it.hasNext()) {
587
            Map.Entry<CacheKey, Object[]> entry = it.next();
585
            Map.Entry<Object, Object[]> entry = it.next();
588
            CacheKey key = entry.getKey();
586
            Object key = entry.getKey();
589
            Object[] previousAndCurrent = entry.getValue();
587
            Object[] previousAndCurrent = entry.getValue();
590
            // previousObject may be null, meaning currentObject has been added to the list
588
            // previousObject may be null, meaning currentObject has been added to the list
591
            Object previousObject = previousAndCurrent[0];
589
            Object previousObject = previousAndCurrent[0];
Lines 595-601 Link Here
595
            if(previousObject == null) {
593
            if(previousObject == null) {
596
                // there's no previous object - that means that current object should be added.
594
                // there's no previous object - that means that current object should be added.
597
                // index of currentObject in currentList
595
                // index of currentObject in currentList
598
                int iCurrent = (Integer)((List)key.getKey()).get(pkSize);
596
                int iCurrent = (Integer)((CacheId)key).getPrimaryKey()[pkSize];
599
                DatabaseRecord extraData = new DatabaseRecord(1);
597
                DatabaseRecord extraData = new DatabaseRecord(1);
600
                extraData.put(this.listOrderField, iCurrent);
598
                extraData.put(this.listOrderField, iCurrent);
601
                
599
                
Lines 624-630 Link Here
624
        }
622
        }
625
        
623
        
626
        // Object[] = {previousObject, currentObject, previousIndex, currentIndex}
624
        // Object[] = {previousObject, currentObject, previousIndex, currentIndex}
627
        HashMap<CacheKey, Object[]> previousAndCurrentByKey = new HashMap<CacheKey, Object[]>();
625
        HashMap<Object, Object[]> previousAndCurrentByKey = new HashMap<Object, Object[]>();
628
        // a SortedMap, current index mapped by previous index, both indexes must exist and be not equal.
626
        // a SortedMap, current index mapped by previous index, both indexes must exist and be not equal.
629
        TreeMap<Integer, Integer> currentIndexByPreviousIndex = new TreeMap<Integer, Integer>();
627
        TreeMap<Integer, Integer> currentIndexByPreviousIndex = new TreeMap<Integer, Integer>();
630
628
Lines 633-641 Link Here
633
            Object currentObject = currentList.get(i);
631
            Object currentObject = currentList.get(i);
634
            try {
632
            try {
635
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
633
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
636
                CacheKey key = new CacheKey(primaryKey);
637
                Object[] previousAndCurrent = new Object[]{null, currentObject, null, i};
634
                Object[] previousAndCurrent = new Object[]{null, currentObject, null, i};
638
                previousAndCurrentByKey.put(key, previousAndCurrent);
635
                previousAndCurrentByKey.put(primaryKey, previousAndCurrent);
639
            } catch (NullPointerException e) {
636
            } catch (NullPointerException e) {
640
                // For CR#2646 quietly discard nulls added to a collection mapping.
637
                // For CR#2646 quietly discard nulls added to a collection mapping.
641
                // This try-catch is essentially a null check on currentObject, for
638
                // This try-catch is essentially a null check on currentObject, for
Lines 650-657 Link Here
650
        for(int i=0; i < previousList.size(); i++) {
647
        for(int i=0; i < previousList.size(); i++) {
651
            Object previousObject = previousList.get(i);
648
            Object previousObject = previousList.get(i);
652
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
649
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
653
            CacheKey key = new CacheKey(primaryKey);
650
            Object[] previousAndCurrent = previousAndCurrentByKey.get(primaryKey);
654
            Object[] previousAndCurrent = previousAndCurrentByKey.get(key);
655
            if(previousAndCurrent == null) {
651
            if(previousAndCurrent == null) {
656
                // there's no current object - that means that previous object should be deleted
652
                // there's no current object - that means that previous object should be deleted
657
                objectRemovedDuringUpdate(query, previousObject, null);
653
                objectRemovedDuringUpdate(query, previousObject, null);
Lines 693-702 Link Here
693
            }
689
            }
694
690
695
            if(shouldUpdateOrderUsingPk) {
691
            if(shouldUpdateOrderUsingPk) {
696
                Iterator<Map.Entry<CacheKey, Object[]>> it = previousAndCurrentByKey.entrySet().iterator();
692
                Iterator<Map.Entry<Object, Object[]>> it = previousAndCurrentByKey.entrySet().iterator();
697
                while(it.hasNext()) {
693
                while(it.hasNext()) {
698
                    Map.Entry<CacheKey, Object[]> entry = it.next();
694
                    Map.Entry<Object, Object[]> entry = it.next();
699
                    CacheKey key = entry.getKey();
695
                    Object key = entry.getKey();
700
                    Object[] previousAndCurrent = entry.getValue();
696
                    Object[] previousAndCurrent = entry.getValue();
701
                    // previousObject may be null, meaning currentObject has been added to the list
697
                    // previousObject may be null, meaning currentObject has been added to the list
702
                    Object previousObject = previousAndCurrent[0];                    
698
                    Object previousObject = previousAndCurrent[0];                    
Lines 715-723 Link Here
715
            } else {
711
            } else {
716
                // update the objects - but not their order values
712
                // update the objects - but not their order values
717
                if(!this.isEntireObjectPK) {
713
                if(!this.isEntireObjectPK) {
718
                    Iterator<Map.Entry<CacheKey, Object[]>> iterator = previousAndCurrentByKey.entrySet().iterator();
714
                    Iterator<Map.Entry<Object, Object[]>> iterator = previousAndCurrentByKey.entrySet().iterator();
719
                    while (iterator.hasNext()) {
715
                    while (iterator.hasNext()) {
720
                        Map.Entry<CacheKey, Object[]> entry = iterator.next();
716
                        Map.Entry<Object, Object[]> entry = iterator.next();
721
                        Object[] previousAndCurrent = entry.getValue();
717
                        Object[] previousAndCurrent = entry.getValue();
722
                        // previousObject may be null, meaning currentObject has been added to the list
718
                        // previousObject may be null, meaning currentObject has been added to the list
723
                        Object previousObject = previousAndCurrent[0];
719
                        Object previousObject = previousAndCurrent[0];
Lines 814-822 Link Here
814
        }
810
        }
815
        
811
        
816
        // Add the new objects
812
        // Add the new objects
817
        Iterator<Map.Entry<CacheKey, Object[]>> iterator = previousAndCurrentByKey.entrySet().iterator();
813
        Iterator<Map.Entry<Object, Object[]>> iterator = previousAndCurrentByKey.entrySet().iterator();
818
        while (iterator.hasNext()) {
814
        while (iterator.hasNext()) {
819
            Map.Entry<CacheKey, Object[]> entry = iterator.next();
815
            Map.Entry<Object, Object[]> entry = iterator.next();
820
            Object[] previousAndCurrent = entry.getValue();
816
            Object[] previousAndCurrent = entry.getValue();
821
            // previousObject may be null, meaning currentObject has been added to the list
817
            // previousObject may be null, meaning currentObject has been added to the list
822
            Object previousObject = previousAndCurrent[0];
818
            Object previousObject = previousAndCurrent[0];
Lines 853-867 Link Here
853
        return (Integer)query.getSession().executeQuery(updateQuery, translationRow);
849
        return (Integer)query.getSession().executeQuery(updateQuery, translationRow);
854
    }
850
    }
855
851
856
    protected int objectChangedListOrderDuringUpdate(WriteObjectQuery query, CacheKey key, int newOrderValue) {
852
    protected int objectChangedListOrderDuringUpdate(WriteObjectQuery query, Object key, int newOrderValue) {
857
        AbstractRecord translationRow = (AbstractRecord)query.getTranslationRow().clone();
853
        AbstractRecord translationRow = (AbstractRecord)query.getTranslationRow().clone();
858
        translationRow.put(this.listOrderField, newOrderValue);
854
        translationRow.put(this.listOrderField, newOrderValue);
859
        List pkValues = key.getKey();
855
        getReferenceDescriptor().getObjectBuilder().writeIntoRowFromPrimaryKeyValues(translationRow, key, query.getSession(), true);
860
        List<DatabaseField> pkFields = getReferenceDescriptor().getPrimaryKeyFields(); 
861
        int size = pkFields.size();
862
        for(int i=0; i < size; i++) {
863
            translationRow.put(pkFields.get(i), pkValues.get(i));
864
        }
865
        return (Integer)query.getSession().executeQuery(this.pkUpdateListOrderFieldQuery, translationRow);
856
        return (Integer)query.getSession().executeQuery(this.pkUpdateListOrderFieldQuery, translationRow);
866
    }
857
    }
867
858
Lines 1001-1025 Link Here
1001
     * Extract the source primary key value from the target row.
992
     * Extract the source primary key value from the target row.
1002
     * Used for batch reading, most following same order and fields as in the mapping.
993
     * Used for batch reading, most following same order and fields as in the mapping.
1003
     */
994
     */
1004
    protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
995
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
1005
        Vector key = new Vector(getTargetForeignKeyFields().size());
996
        int size = this.targetForeignKeyFields.size();
997
        Object[] key = new Object[size];
1006
998
1007
        for (int index = 0; index < getTargetForeignKeyFields().size(); index++) {
999
        for (int index = 0; index < size; index++) {
1008
            DatabaseField targetField = getTargetForeignKeyFields().elementAt(index);
1000
            DatabaseField targetField = this.targetForeignKeyFields.get(index);
1009
            DatabaseField sourceField = getSourceKeyFields().elementAt(index);
1001
            DatabaseField sourceField = this.sourceKeyFields.get(index);
1010
            Object value = row.get(targetField);
1002
            Object value = row.get(targetField);
1011
1003
1012
            // Must ensure the classification gets a cache hit.
1004
            // Must ensure the classification gets a cache hit.
1013
            try {
1005
            try {
1014
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceField));
1006
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, this.descriptor.getObjectBuilder().getFieldClassification(sourceField));
1015
            } catch (ConversionException e) {
1007
            } catch (ConversionException e) {
1016
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
1008
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
1017
            }
1009
            }
1018
1010
1019
            key.addElement(value);
1011
            key[index] = value;
1020
        }
1012
        }
1021
1013
        return new CacheId(key);
1022
        return key;
1023
    }
1014
    }
1024
1015
1025
    /**
1016
    /**
Lines 1027-1050 Link Here
1027
     * Extract the primary key value from the source row.
1018
     * Extract the primary key value from the source row.
1028
     * Used for batch reading, most following same order and fields as in the mapping.
1019
     * Used for batch reading, most following same order and fields as in the mapping.
1029
     */
1020
     */
1030
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
1021
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
1031
        Vector key = new Vector(getSourceKeyFields().size());
1022
        int size = this.sourceKeyFields.size();
1023
        Object[] key = new Object[size];
1024
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
1032
1025
1033
        for (Enumeration fieldEnum = getSourceKeyFields().elements(); fieldEnum.hasMoreElements();) {
1026
        for (int index = 0; index < size; index++) {
1034
            DatabaseField field = (DatabaseField)fieldEnum.nextElement();
1027
            DatabaseField field = this.sourceKeyFields.get(index);
1035
            Object value = row.get(field);
1028
            Object value = row.get(field);
1036
1029
1037
            // Must ensure the classification gets a cache hit.
1030
            // Must ensure the classification gets a cache hit.
1038
            try {
1031
            try {
1039
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
1032
                value = conversionManager.convertObject(value, this.descriptor.getObjectBuilder().getFieldClassification(field));
1040
            } catch (ConversionException e) {
1033
            } catch (ConversionException e) {
1041
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
1034
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
1042
            }
1035
            }
1043
1036
1044
            key.addElement(value);
1037
            key[index] = value;
1045
        }
1038
        }
1046
1039
        
1047
        return key;
1040
        return new CacheId(key);
1048
    }
1041
    }
1049
1042
1050
    /**
1043
    /**
Lines 1104-1110 Link Here
1104
     * descriptor is part of an inheritance tree.
1097
     * descriptor is part of an inheritance tree.
1105
     */
1098
     */
1106
    public ClassDescriptor getReferenceDescriptor() {
1099
    public ClassDescriptor getReferenceDescriptor() {
1107
        if(referenceDescriptor == null) {
1100
        if (referenceDescriptor == null) {
1108
            referenceDescriptor = remoteReferenceDescriptor;
1101
            referenceDescriptor = remoteReferenceDescriptor;
1109
        }
1102
        }
1110
        return referenceDescriptor;
1103
        return referenceDescriptor;
Lines 1220-1229 Link Here
1220
     */
1213
     */
1221
    public void initialize(AbstractSession session) throws DescriptorException {
1214
    public void initialize(AbstractSession session) throws DescriptorException {
1222
        super.initialize(session);
1215
        super.initialize(session);
1223
        if (getDescriptor() != null){ // descriptor will only be null in special case where the mapping has not been added to a descriptor prior to initialization.
1216
        if (getDescriptor() != null) { // descriptor will only be null in special case where the mapping has not been added to a descriptor prior to initialization.
1224
            getDescriptor().addMappingsPostCalculateChanges(this); // always equivalent to Private Owned
1217
            getDescriptor().addMappingsPostCalculateChanges(this); // always equivalent to Private Owned
1225
            if (getDescriptor().hasInheritance()){
1218
            if (getDescriptor().hasInheritance()) {
1226
                for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
1219
                for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
1227
                    descriptor.addMappingsPostCalculateChanges(this);
1220
                    descriptor.addMappingsPostCalculateChanges(this);
1228
                }
1221
                }
1229
            }
1222
            }
Lines 1546-1562 Link Here
1546
        //recursive call to further children descriptors
1539
        //recursive call to further children descriptors
1547
        if (parentDescriptor.getInheritancePolicy().hasChildren()) {
1540
        if (parentDescriptor.getInheritancePolicy().hasChildren()) {
1548
            //setFields(clonedChildDescriptor.getFields());		
1541
            //setFields(clonedChildDescriptor.getFields());		
1549
            Vector childDescriptors = parentDescriptor.getInheritancePolicy().getChildDescriptors();
1542
            List<ClassDescriptor> childDescriptors = parentDescriptor.getInheritancePolicy().getChildDescriptors();
1550
            Vector cloneChildDescriptors = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
1543
            List<ClassDescriptor> cloneChildDescriptors = new ArrayList(childDescriptors.size());
1551
            for (Enumeration enumtr = childDescriptors.elements(); enumtr.hasMoreElements();) {
1544
            for (ClassDescriptor childDescriptor : childDescriptors) {
1552
                ClassDescriptor clonedChildDescriptor = (ClassDescriptor)((ClassDescriptor)enumtr.nextElement()).clone();
1545
                ClassDescriptor clonedChildDescriptor = (ClassDescriptor)childDescriptor.clone();
1553
                if(fieldTranslation != null) {
1546
                if (fieldTranslation != null) {
1554
                    translateTablesAndFields(clonedChildDescriptor, fieldTranslation, tableTranslation); 
1547
                    translateTablesAndFields(clonedChildDescriptor, fieldTranslation, tableTranslation); 
1555
                }
1548
                }
1556
                
1549
                
1557
                updateNestedAggregateMappings(clonedChildDescriptor, session);
1550
                updateNestedAggregateMappings(clonedChildDescriptor, session);
1558
                
1551
                
1559
                if(clonedChildDescriptor.isAggregateDescriptor()) {
1552
                if (clonedChildDescriptor.isAggregateDescriptor()) {
1560
                    clonedChildDescriptor.descriptorIsAggregateCollection();
1553
                    clonedChildDescriptor.descriptorIsAggregateCollection();
1561
                }
1554
                }
1562
                if (!clonedChildDescriptor.isAggregateCollectionDescriptor()) {
1555
                if (!clonedChildDescriptor.isAggregateCollectionDescriptor()) {
Lines 1566-1572 Link Here
1566
                clonedChildDescriptor.getInheritancePolicy().setParentDescriptor(parentDescriptor);
1559
                clonedChildDescriptor.getInheritancePolicy().setParentDescriptor(parentDescriptor);
1567
                clonedChildDescriptor.preInitialize(session);
1560
                clonedChildDescriptor.preInitialize(session);
1568
                clonedChildDescriptor.initialize(session);
1561
                clonedChildDescriptor.initialize(session);
1569
                cloneChildDescriptors.addElement(clonedChildDescriptor);
1562
                cloneChildDescriptors.add(clonedChildDescriptor);
1570
                initializeChildInheritance(clonedChildDescriptor, session, fieldTranslation, tableTranslation);
1563
                initializeChildInheritance(clonedChildDescriptor, session, fieldTranslation, tableTranslation);
1571
            }
1564
            }
1572
            parentDescriptor.getInheritancePolicy().setChildDescriptors(cloneChildDescriptors);
1565
            parentDescriptor.getInheritancePolicy().setChildDescriptors(cloneChildDescriptors);
Lines 1905-1911 Link Here
1905
     * INTERNAL:
1898
     * INTERNAL:
1906
     * An object is still in the collection, update it as it may have changed.
1899
     * An object is still in the collection, update it as it may have changed.
1907
     */
1900
     */
1908
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Hashtable backupCloneKeyedCache, CacheKey cachedKey) throws DatabaseException, OptimisticLockException {
1901
    @Override
1902
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Map backupCloneKeyedCache, Object cachedKey) throws DatabaseException, OptimisticLockException {
1909
        // Always write for updates, either private or in uow if calling this method.
1903
        // Always write for updates, either private or in uow if calling this method.
1910
        UpdateObjectQuery updateQuery = new UpdateObjectQuery();
1904
        UpdateObjectQuery updateQuery = new UpdateObjectQuery();
1911
        updateQuery.setIsExecutionClone(true);
1905
        updateQuery.setIsExecutionClone(true);
Lines 1914-1919 Link Here
1914
        prepareModifyQueryForUpdate(query, updateQuery, object);
1908
        prepareModifyQueryForUpdate(query, updateQuery, object);
1915
        query.getSession().executeQuery(updateQuery, updateQuery.getTranslationRow());
1909
        query.getSession().executeQuery(updateQuery, updateQuery.getTranslationRow());
1916
    }
1910
    }
1911
    
1917
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Object backupClone) throws DatabaseException, OptimisticLockException {
1912
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Object backupClone) throws DatabaseException, OptimisticLockException {
1918
        // Always write for updates, either private or in uow if calling this method.
1913
        // Always write for updates, either private or in uow if calling this method.
1919
        UpdateObjectQuery updateQuery = new UpdateObjectQuery();
1914
        UpdateObjectQuery updateQuery = new UpdateObjectQuery();
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/AggregateObjectMapping.java (-11 / +7 lines)
Lines 583-594 Link Here
583
        AbstractRecord result = getReferenceDescriptor().getObjectBuilder().buildTemplateInsertRow(session);
583
        AbstractRecord result = getReferenceDescriptor().getObjectBuilder().buildTemplateInsertRow(session);
584
        List processedMappings = (List)getReferenceDescriptor().getMappings().clone();
584
        List processedMappings = (List)getReferenceDescriptor().getMappings().clone();
585
        if (getReferenceDescriptor().hasInheritance()) {
585
        if (getReferenceDescriptor().hasInheritance()) {
586
            Enumeration children = getReferenceDescriptor().getInheritancePolicy().getChildDescriptors().elements();
586
            for (ClassDescriptor child : getReferenceDescriptor().getInheritancePolicy().getChildDescriptors()) {
587
            while (children.hasMoreElements()) {
587
                for (DatabaseMapping mapping : child.getMappings()) {
588
                Enumeration mappings = ((ClassDescriptor)children.nextElement()).getMappings().elements();
589
                while (mappings.hasMoreElements()) {
590
                    DatabaseMapping mapping = (DatabaseMapping)mappings.nextElement();
591
592
                    // Only write mappings once.
588
                    // Only write mappings once.
593
                    if (!processedMappings.contains(mapping)) {
589
                    if (!processedMappings.contains(mapping)) {
594
                        mapping.writeInsertFieldsIntoRow(result, session);
590
                        mapping.writeInsertFieldsIntoRow(result, session);
Lines 1067-1082 Link Here
1067
        //recursive call to the further children descriptors
1063
        //recursive call to the further children descriptors
1068
        if (parentDescriptor.getInheritancePolicy().hasChildren()) {
1064
        if (parentDescriptor.getInheritancePolicy().hasChildren()) {
1069
            //setFields(clonedChildDescriptor.getFields());		
1065
            //setFields(clonedChildDescriptor.getFields());		
1070
            Vector childDescriptors = parentDescriptor.getInheritancePolicy().getChildDescriptors();
1066
            List<ClassDescriptor> childDescriptors = parentDescriptor.getInheritancePolicy().getChildDescriptors();
1071
            Vector cloneChildDescriptors = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
1067
            List<ClassDescriptor> cloneChildDescriptors = new ArrayList();
1072
            for (Enumeration enumtr = childDescriptors.elements(); enumtr.hasMoreElements();) {
1068
            for (ClassDescriptor child : childDescriptors) {
1073
                ClassDescriptor clonedChildDescriptor = (ClassDescriptor)((ClassDescriptor)enumtr.nextElement()).clone();
1069
                ClassDescriptor clonedChildDescriptor = (ClassDescriptor)child.clone();
1074
                clonedChildDescriptor.getInheritancePolicy().setParentDescriptor(parentDescriptor);
1070
                clonedChildDescriptor.getInheritancePolicy().setParentDescriptor(parentDescriptor);
1075
                initializeReferenceDescriptor(clonedChildDescriptor);
1071
                initializeReferenceDescriptor(clonedChildDescriptor);
1076
                clonedChildDescriptor.preInitialize(session);
1072
                clonedChildDescriptor.preInitialize(session);
1077
                clonedChildDescriptor.initialize(session);
1073
                clonedChildDescriptor.initialize(session);
1078
                translateFields(clonedChildDescriptor, session);
1074
                translateFields(clonedChildDescriptor, session);
1079
                cloneChildDescriptors.addElement(clonedChildDescriptor);
1075
                cloneChildDescriptors.add(clonedChildDescriptor);
1080
                initializeChildInheritance(clonedChildDescriptor, session);
1076
                initializeChildInheritance(clonedChildDescriptor, session);
1081
            }
1077
            }
1082
            parentDescriptor.getInheritancePolicy().setChildDescriptors(cloneChildDescriptors);
1078
            parentDescriptor.getInheritancePolicy().setChildDescriptors(cloneChildDescriptors);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/CollectionMapping.java (-65 / +57 lines)
Lines 29-35 Link Here
29
import org.eclipse.persistence.internal.descriptors.*;
29
import org.eclipse.persistence.internal.descriptors.*;
30
import org.eclipse.persistence.internal.expressions.*;
30
import org.eclipse.persistence.internal.expressions.*;
31
import org.eclipse.persistence.internal.helper.*;
31
import org.eclipse.persistence.internal.helper.*;
32
import org.eclipse.persistence.internal.identitymaps.*;
33
import org.eclipse.persistence.internal.indirection.*;
32
import org.eclipse.persistence.internal.indirection.*;
34
import org.eclipse.persistence.internal.queries.*;
33
import org.eclipse.persistence.internal.queries.*;
35
import org.eclipse.persistence.internal.sessions.remote.*;
34
import org.eclipse.persistence.internal.sessions.remote.*;
Lines 533-539 Link Here
533
                        containerPolicy.propogatePostUpdate(query, addedChangeSet.getNewKey());
532
                        containerPolicy.propogatePostUpdate(query, addedChangeSet.getNewKey());
534
                    }
533
                    }
535
                }
534
                }
536
                if(listOrderField != null) {
535
                if (listOrderField != null) {
537
                    List previousList = (List)previousObjects;
536
                    List previousList = (List)previousObjects;
538
                    int previousSize = previousList.size();
537
                    int previousSize = previousList.size();
539
                    List currentList = (List)currentObjects;
538
                    List currentList = (List)currentObjects;
Lines 562-568 Link Here
562
                            }
561
                            }
563
                        }
562
                        }
564
                    } else {
563
                    } else {
565
                        for(int i=0; i < previousSize; i++) {
564
                        for (int i=0; i < previousSize; i++) {
566
                            // TODO: should we check for previousObject != null? 
565
                            // TODO: should we check for previousObject != null? 
567
                            Object prevObject = previousList.get(i);
566
                            Object prevObject = previousList.get(i);
568
                            Object currentObject = null;
567
                            Object currentObject = null;
Lines 578-584 Link Here
578
                            }
577
                            }
579
                        }
578
                        }
580
                    }
579
                    }
581
                    if(shouldRepairOrder) {
580
                    if (shouldRepairOrder) {
582
                        ((IndirectList)currentList).setIsListOrderBrokenInDb(false);
581
                        ((IndirectList)currentList).setIsListOrderBrokenInDb(false);
583
                        record.setOrderHasBeenRepaired(true);
582
                        record.setOrderHasBeenRepaired(true);
584
                    }
583
                    }
Lines 587-603 Link Here
587
            return;
586
            return;
588
        }
587
        }
589
        
588
        
590
        if(this.listOrderField != null && this.isAggregateCollectionMapping()) {
589
        if (this.listOrderField != null && this.isAggregateCollectionMapping()) {
591
            this.compareListsAndWrite((List)previousObjects, (List)currentObjects, query);
590
            this.compareListsAndWrite((List)previousObjects, (List)currentObjects, query);
592
            return;
591
            return;
593
        }
592
        }
594
        
593
        
595
        ContainerPolicy cp = this.containerPolicy;
594
        ContainerPolicy cp = this.containerPolicy;
596
595
597
        Hashtable previousObjectsByKey = new Hashtable(cp.sizeFor(previousObjects) + 2); // Read from db or from backup in uow.
596
        Map previousObjectsByKey = new HashMap(cp.sizeFor(previousObjects)); // Read from db or from backup in uow.
598
        Hashtable currentObjectsByKey = new Hashtable(cp.sizeFor(currentObjects) + 2); // Current value of object's attribute (clone in uow).
597
        Map currentObjectsByKey = new HashMap(cp.sizeFor(currentObjects)); // Current value of object's attribute (clone in uow).
599
598
600
        Map cacheKeysOfCurrentObjects = new IdentityHashMap(cp.sizeFor(currentObjects) + 1);
599
        Map keysOfCurrentObjects = new IdentityHashMap(cp.sizeFor(currentObjects) + 1);
601
600
602
        // First index the current objects by their primary key.
601
        // First index the current objects by their primary key.
603
        for (Object currentObjectsIter = cp.iteratorFor(currentObjects);
602
        for (Object currentObjectsIter = cp.iteratorFor(currentObjects);
Lines 605-613 Link Here
605
            Object currentObject = cp.next(currentObjectsIter, query.getSession());
604
            Object currentObject = cp.next(currentObjectsIter, query.getSession());
606
            try {
605
            try {
607
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
606
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
608
                CacheKey key = new CacheKey(primaryKey);
607
                currentObjectsByKey.put(primaryKey, currentObject);
609
                currentObjectsByKey.put(key, currentObject);
608
                keysOfCurrentObjects.put(currentObject, primaryKey);
610
                cacheKeysOfCurrentObjects.put(currentObject, key);
611
            } catch (NullPointerException e) {
609
            } catch (NullPointerException e) {
612
                // For CR#2646 quietly discard nulls added to a collection mapping.
610
                // For CR#2646 quietly discard nulls added to a collection mapping.
613
                // This try-catch is essentially a null check on currentObject, for
611
                // This try-catch is essentially a null check on currentObject, for
Lines 626-636 Link Here
626
            Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
624
            Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
627
            Object previousObject = containerPolicy.unwrapIteratorResult(wrappedObject);
625
            Object previousObject = containerPolicy.unwrapIteratorResult(wrappedObject);
628
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
626
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
629
            CacheKey key = new CacheKey(primaryKey);
627
            previousObjectsByKey.put(primaryKey, previousObject);
630
            previousObjectsByKey.put(key, previousObject);
631
            // Delete must occur first, in case object with same pk is removed and added,
628
            // Delete must occur first, in case object with same pk is removed and added,
632
            // (technically should not happen, but same applies to unique constraints)
629
            // (technically should not happen, but same applies to unique constraints)
633
            if (!currentObjectsByKey.containsKey(key)) {
630
            if (!currentObjectsByKey.containsKey(primaryKey)) {
634
                objectRemovedDuringUpdate(query, wrappedObject, mapKeyFields);
631
                objectRemovedDuringUpdate(query, wrappedObject, mapKeyFields);
635
                cp.propogatePostUpdate(query, wrappedObject);
632
                cp.propogatePostUpdate(query, wrappedObject);
636
            }
633
            }
Lines 642-654 Link Here
642
            Object currentObject = containerPolicy.unwrapIteratorResult(wrappedObject);
639
            Object currentObject = containerPolicy.unwrapIteratorResult(wrappedObject);
643
            try {
640
            try {
644
                Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
641
                Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
645
                CacheKey cacheKey = (CacheKey)cacheKeysOfCurrentObjects.get(currentObject);
642
                Object primaryKey = keysOfCurrentObjects.get(currentObject);
646
643
647
                if (!(previousObjectsByKey.containsKey(cacheKey))) {
644
                if (!(previousObjectsByKey.containsKey(primaryKey))) {
648
                    objectAddedDuringUpdate(query, currentObject, null, mapKeyFields);
645
                    objectAddedDuringUpdate(query, currentObject, null, mapKeyFields);
649
                    cp.propogatePostUpdate(query, wrappedObject);
646
                    cp.propogatePostUpdate(query, wrappedObject);
650
                } else {
647
                } else {
651
                    objectUnchangedDuringUpdate(query, currentObject, previousObjectsByKey, cacheKey);
648
                    objectUnchangedDuringUpdate(query, currentObject, previousObjectsByKey, primaryKey);
652
                }
649
                }
653
            } catch (NullPointerException e) {
650
            } catch (NullPointerException e) {
654
                // For CR#2646 skip currentObject if it is null.
651
                // For CR#2646 skip currentObject if it is null.
Lines 685-703 Link Here
685
        Object firstIter = cp.iteratorFor(firstCollection);
682
        Object firstIter = cp.iteratorFor(firstCollection);
686
        Object secondIter = cp.iteratorFor(secondCollection);
683
        Object secondIter = cp.iteratorFor(secondCollection);
687
684
688
        Vector keyValue = new Vector();
685
        Set keyValue = new HashSet();
689
686
690
        while (cp.hasNext(secondIter)) {
687
        while (cp.hasNext(secondIter)) {
691
            Object secondObject = cp.next(secondIter, session);
688
            Object secondObject = cp.next(secondIter, session);
692
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
689
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
693
            keyValue.add(new CacheKey(primaryKey));
690
            keyValue.add(primaryKey);
694
        }
691
        }
695
692
696
        while (cp.hasNext(firstIter)) {
693
        while (cp.hasNext(firstIter)) {
697
            Object firstObject = cp.next(firstIter, session);
694
            Object firstObject = cp.next(firstIter, session);
698
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
695
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
699
696
700
            if (!keyValue.contains(new CacheKey(primaryKey))) {
697
            if (!keyValue.contains(primaryKey)) {
701
                return false;
698
                return false;
702
            }
699
            }
703
        }
700
        }
Lines 720-742 Link Here
720
        Object firstIter = cp.iteratorFor(firstCollection);
717
        Object firstIter = cp.iteratorFor(firstCollection);
721
        Object secondIter = cp.iteratorFor(secondCollection);
718
        Object secondIter = cp.iteratorFor(secondCollection);
722
719
723
        Hashtable keyValueToObject = new Hashtable(cp.sizeFor(firstCollection) + 2);
720
        Map keyValueToObject = new HashMap(cp.sizeFor(firstCollection));
724
        CacheKey cacheKey;
725
721
726
        while (cp.hasNext(secondIter)) {
722
        while (cp.hasNext(secondIter)) {
727
            Object secondObject = cp.next(secondIter, session);
723
            Object secondObject = cp.next(secondIter, session);
728
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
724
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
729
            keyValueToObject.put(new CacheKey(primaryKey), secondObject);
725
            keyValueToObject.put(primaryKey, secondObject);
730
        }
726
        }
731
727
732
        while (cp.hasNext(firstIter)) {
728
        while (cp.hasNext(firstIter)) {
733
            Object firstObject = cp.next(firstIter, session);
729
            Object firstObject = cp.next(firstIter, session);
734
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
730
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
735
            cacheKey = new CacheKey(primaryKey);
731
            
732
            if (keyValueToObject.containsKey(primaryKey)) {
733
                Object object = keyValueToObject.get(primaryKey);
736
734
737
            if (keyValueToObject.containsKey(cacheKey)) {
738
                Object object = keyValueToObject.get(cacheKey);
739
740
                if (!session.compareObjects(firstObject, object)) {
735
                if (!session.compareObjects(firstObject, object)) {
741
                    return false;
736
                    return false;
742
                }
737
                }
Lines 766-774 Link Here
766
                    return false;
761
                    return false;
767
                }
762
                }
768
            } else {
763
            } else {
769
                CacheKey firstKey = new CacheKey(getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session));
764
                Object firstKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
770
                CacheKey secondKey = new CacheKey(getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session));
765
                Object secondKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
771
                if(!firstKey.equals(secondKey)) {
766
                if (!firstKey.equals(secondKey)) {
772
                    return false;
767
                    return false;
773
                }
768
                }
774
            }
769
            }
Lines 794-800 Link Here
794
     */
789
     */
795
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
790
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
796
        //this can be null, because either one exists in the query or it will be created
791
        //this can be null, because either one exists in the query or it will be created
797
        Hashtable referenceObjectsByKey = null;
792
        Map<Object, Object> referenceObjectsByKey = null;
798
        synchronized (query) {
793
        synchronized (query) {
799
            referenceObjectsByKey = getBatchReadObjects(query, session);
794
            referenceObjectsByKey = getBatchReadObjects(query, session);
800
            if (referenceObjectsByKey == null) {
795
            if (referenceObjectsByKey == null) {
Lines 802-818 Link Here
802
                ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(batchQuery, argumentRow);
797
                ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(batchQuery, argumentRow);
803
                Object results = complexResult.getResult();
798
                Object results = complexResult.getResult();
804
                referenceObjectsByKey = new Hashtable();
799
                referenceObjectsByKey = new Hashtable();
805
                Enumeration rowsEnum = ((Vector)complexResult.getData()).elements();
800
                Iterator<AbstractRecord> rowsIterator = ((List<AbstractRecord>)complexResult.getData()).iterator();
806
                ContainerPolicy queryContainerPolicy = batchQuery.getContainerPolicy();
801
                ContainerPolicy queryContainerPolicy = batchQuery.getContainerPolicy();
807
                if(this.containerPolicy.shouldAddAll()) {
802
                if (this.containerPolicy.shouldAddAll()) {
808
                    HashMap<CacheKey, List[]> referenceObjectsAndRowsByKey = new HashMap();
803
                    Map<Object, List[]> referenceObjectsAndRowsByKey = new HashMap();
809
                    for (Object elementsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(elementsIterator);) {
804
                    for (Object elementsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(elementsIterator);) {
810
                        Object eachReferenceObject = queryContainerPolicy.next(elementsIterator, session);
805
                        Object eachReferenceObject = queryContainerPolicy.next(elementsIterator, session);
811
                        AbstractRecord row = (AbstractRecord)rowsEnum.nextElement();
806
                        AbstractRecord row = rowsIterator.next();
812
                        CacheKey eachReferenceKey = new CacheKey(extractKeyFromTargetRow(row, session));
807
                        Object eachReferenceKey = extractKeyFromTargetRow(row, session);                        
813
                        
814
                        List[] objectsAndRows = referenceObjectsAndRowsByKey.get(eachReferenceKey);
808
                        List[] objectsAndRows = referenceObjectsAndRowsByKey.get(eachReferenceKey);
815
                        if(objectsAndRows == null) {
809
                        if (objectsAndRows == null) {
816
                            objectsAndRows = new List[]{new ArrayList(), new ArrayList()};
810
                            objectsAndRows = new List[]{new ArrayList(), new ArrayList()};
817
                            referenceObjectsAndRowsByKey.put(eachReferenceKey, objectsAndRows);
811
                            referenceObjectsAndRowsByKey.put(eachReferenceKey, objectsAndRows);
818
                        }
812
                        }
Lines 820-829 Link Here
820
                        objectsAndRows[1].add(row);
814
                        objectsAndRows[1].add(row);
821
                    }
815
                    }
822
816
823
                    Iterator<Map.Entry<CacheKey, List[]>> it = referenceObjectsAndRowsByKey.entrySet().iterator();
817
                    Iterator<Map.Entry<Object, List[]>> it = referenceObjectsAndRowsByKey.entrySet().iterator();
824
                    while(it.hasNext()) {
818
                    while (it.hasNext()) {
825
                        Map.Entry<CacheKey, List[]> entry = it.next();
819
                        Map.Entry<Object, List[]> entry = it.next();
826
                        CacheKey eachReferenceKey = entry.getKey(); 
820
                        Object eachReferenceKey = entry.getKey(); 
827
                        List objects = entry.getValue()[0];
821
                        List objects = entry.getValue()[0];
828
                        List<AbstractRecord> rows = entry.getValue()[1];
822
                        List<AbstractRecord> rows = entry.getValue()[1];
829
                        Object container = this.containerPolicy.containerInstance(objects.size());
823
                        Object container = this.containerPolicy.containerInstance(objects.size());
Lines 833-840 Link Here
833
                } else {
827
                } else {
834
                    for (Object elementsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(elementsIterator);) {
828
                    for (Object elementsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(elementsIterator);) {
835
                        Object eachReferenceObject = queryContainerPolicy.next(elementsIterator, session);
829
                        Object eachReferenceObject = queryContainerPolicy.next(elementsIterator, session);
836
                        AbstractRecord row = (AbstractRecord)rowsEnum.nextElement();
830
                        AbstractRecord row = rowsIterator.next();
837
                        CacheKey eachReferenceKey = new CacheKey(extractKeyFromTargetRow(row, session));
831
                        Object eachReferenceKey = extractKeyFromTargetRow(row, session);
838
                        
832
                        
839
                        Object container = referenceObjectsByKey.get(eachReferenceKey);
833
                        Object container = referenceObjectsByKey.get(eachReferenceKey);
840
                        if (container == null) {
834
                        if (container == null) {
Lines 848-854 Link Here
848
                query.setSession(null);
842
                query.setSession(null);
849
            }
843
            }
850
        }
844
        }
851
        Object result = referenceObjectsByKey.get(new CacheKey(extractPrimaryKeyFromRow(databaseRow, session)));
845
        Object result = referenceObjectsByKey.get(extractPrimaryKeyFromRow(databaseRow, session));
852
846
853
        // The source object might not have any target objects
847
        // The source object might not have any target objects
854
        if (result == null) {
848
        if (result == null) {
Lines 868-875 Link Here
868
     * The method should be overridden by classes that use batch reading: 
862
     * The method should be overridden by classes that use batch reading: 
869
     * for those classes extractResultFromBatchQuery method is called. 
863
     * for those classes extractResultFromBatchQuery method is called. 
870
     */
864
     */
871
    protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
865
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
872
        return new Vector(0);
866
        return null;
873
    }
867
    }
874
868
875
        /**
869
        /**
Lines 882-889 Link Here
882
     * The method should be overridden by classes that use batch reading: 
876
     * The method should be overridden by classes that use batch reading: 
883
     * for those classes extractResultFromBatchQuery method is called. 
877
     * for those classes extractResultFromBatchQuery method is called. 
884
     */
878
     */
885
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
879
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
886
        return new Vector(0);
880
        return null;
887
    }
881
    }
888
    
882
    
889
    /**
883
    /**
Lines 1700-1706 Link Here
1700
     * INTERNAL:
1694
     * INTERNAL:
1701
     * An object is still in the collection, update it as it may have changed.
1695
     * An object is still in the collection, update it as it may have changed.
1702
     */
1696
     */
1703
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Hashtable backupclones, CacheKey keys) throws DatabaseException, OptimisticLockException {
1697
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Map backupclones, Object key) throws DatabaseException, OptimisticLockException {
1704
        objectUnchangedDuringUpdate(query, object);
1698
        objectUnchangedDuringUpdate(query, object);
1705
    }
1699
    }
1706
1700
Lines 2282-2292 Link Here
2282
        ContainerPolicy cp = this.containerPolicy;
2276
        ContainerPolicy cp = this.containerPolicy;
2283
        Object result = cp.containerInstance(pks.length);
2277
        Object result = cp.containerInstance(pks.length);
2284
        for (int index = 0; index < pks.length; ++index){
2278
        for (int index = 0; index < pks.length; ++index){
2285
            Vector pk = null;
2279
            Object pk = null;
2286
            if (getReferenceDescriptor().hasCMPPolicy()){
2280
            if (getReferenceDescriptor().hasCMPPolicy()){
2287
                pk = getReferenceDescriptor().getCMPPolicy().createPkVectorFromKey(pks[index], session);
2281
                pk = getReferenceDescriptor().getCMPPolicy().createPrimaryKeyFromId(pks[index], session);
2288
            }else{
2282
            }else{
2289
                pk = (Vector)pks[index];
2283
                pk = pks[index];
2290
            }
2284
            }
2291
            ReadObjectQuery query = new ReadObjectQuery();
2285
            ReadObjectQuery query = new ReadObjectQuery();
2292
            query.setReferenceClass(getReferenceClass());
2286
            query.setReferenceClass(getReferenceClass());
Lines 2306-2335 Link Here
2306
2300
2307
        Object value = this.containerPolicy.containerInstance();
2301
        Object value = this.containerPolicy.containerInstance();
2308
        // Extract the primary key of the source object, to filter only the joined rows for that object.
2302
        // Extract the primary key of the source object, to filter only the joined rows for that object.
2309
        Object sourceKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession);
2303
        Object sourceKey = this.descriptor.getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession);
2310
        CacheKey sourceCacheKey = new CacheKey(sourceKey);
2311
        // If the query was using joining, all of the result rows by primary key will have been computed.
2304
        // If the query was using joining, all of the result rows by primary key will have been computed.
2312
        List rows = joinManager.getDataResultsByPrimaryKey().get(sourceCacheKey);
2305
        List<AbstractRecord> rows = joinManager.getDataResultsByPrimaryKey().get(sourceKey);
2313
        int size = rows.size();
2306
        int size = rows.size();
2314
        if(size > 0) {
2307
        if (size > 0) {
2315
            // A nested query must be built to pass to the descriptor that looks like the real query execution would,
2308
            // A nested query must be built to pass to the descriptor that looks like the real query execution would,
2316
            // these should be cached on the query during prepare.
2309
            // these should be cached on the query during prepare.
2317
            ObjectLevelReadQuery nestedQuery = prepareNestedJoinQueryClone(row, rows, joinManager, sourceQuery, executionSession);
2310
            ObjectLevelReadQuery nestedQuery = prepareNestedJoinQueryClone(row, rows, joinManager, sourceQuery, executionSession);
2318
            
2311
            
2319
            // A set of target cache keys must be maintained to avoid duplicates from multiple 1-m joins.
2312
            // A set of target cache keys must be maintained to avoid duplicates from multiple 1-m joins.
2320
            Set targetCacheKeys = new HashSet();
2313
            Set targetPrimaryKeys = new HashSet();
2321
            
2314
            
2322
            ArrayList targetObjects = null;
2315
            ArrayList targetObjects = null;
2323
            ArrayList<AbstractRecord> targetRows = null;
2316
            ArrayList<AbstractRecord> targetRows = null;
2324
            boolean shouldAddAll = this.containerPolicy.shouldAddAll();
2317
            boolean shouldAddAll = this.containerPolicy.shouldAddAll();
2325
            if(shouldAddAll) {
2318
            if (shouldAddAll) {
2326
                targetObjects = new ArrayList(size);
2319
                targetObjects = new ArrayList(size);
2327
                targetRows = new ArrayList(size);
2320
                targetRows = new ArrayList(size);
2328
            }
2321
            }
2329
            
2322
            
2330
            // For each rows, extract the target row and build the target object and add to the collection.
2323
            // For each rows, extract the target row and build the target object and add to the collection.
2331
            for (int index = 0; index < size; index++) {
2324
            for (int index = 0; index < size; index++) {
2332
                AbstractRecord sourceRow = (AbstractRecord)rows.get(index);
2325
                AbstractRecord sourceRow = rows.get(index);
2333
                AbstractRecord targetRow = sourceRow;
2326
                AbstractRecord targetRow = sourceRow;
2334
                // The field for many objects may be in the row,
2327
                // The field for many objects may be in the row,
2335
                // so build the subpartion of the row through the computed values in the query,
2328
                // so build the subpartion of the row through the computed values in the query,
Lines 2344-2359 Link Here
2344
                    return this.indirectionPolicy.valueFromRow(value);
2337
                    return this.indirectionPolicy.valueFromRow(value);
2345
                }
2338
                }
2346
                
2339
                
2347
                CacheKey targetCacheKey = new CacheKey(targetKey);            
2348
                // Only build/add the target object once, skip duplicates from multiple 1-m joins.
2340
                // Only build/add the target object once, skip duplicates from multiple 1-m joins.
2349
                if (!targetCacheKeys.contains(targetCacheKey)) {
2341
                if (!targetPrimaryKeys.contains(targetKey)) {
2350
                    nestedQuery.setTranslationRow(targetRow);
2342
                    nestedQuery.setTranslationRow(targetRow);
2351
                    targetCacheKeys.add(targetCacheKey);
2343
                    targetPrimaryKeys.add(targetKey);
2352
                    Object targetObject = getReferenceDescriptor().getObjectBuilder().buildObject(nestedQuery, targetRow);
2344
                    Object targetObject = getReferenceDescriptor().getObjectBuilder().buildObject(nestedQuery, targetRow);
2353
                    Object targetMapKey = this.containerPolicy.buildKeyFromJoinedRow(targetRow, joinManager, nestedQuery, executionSession);
2345
                    Object targetMapKey = this.containerPolicy.buildKeyFromJoinedRow(targetRow, joinManager, nestedQuery, executionSession);
2354
                    nestedQuery.setTranslationRow(null);
2346
                    nestedQuery.setTranslationRow(null);
2355
                    if (targetMapKey == null){
2347
                    if (targetMapKey == null){
2356
                        if(shouldAddAll) {
2348
                        if (shouldAddAll) {
2357
                            targetObjects.add(targetObject);
2349
                            targetObjects.add(targetObject);
2358
                            targetRows.add(targetRow);
2350
                            targetRows.add(targetRow);
2359
                        } else {
2351
                        } else {
Lines 2364-2370 Link Here
2364
                    }
2356
                    }
2365
                }
2357
                }
2366
            }
2358
            }
2367
            if(shouldAddAll) {
2359
            if (shouldAddAll) {
2368
                this.containerPolicy.addAll(targetObjects, value, executionSession, targetRows, nestedQuery);
2360
                this.containerPolicy.addAll(targetObjects, value, executionSession, targetRows, nestedQuery);
2369
            }
2361
            }
2370
        }
2362
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/DirectCollectionMapping.java (-40 / +41 lines)
Lines 268-282 Link Here
268
     * Return the value of the field from the row or a value holder on the query to obtain the object.
268
     * Return the value of the field from the row or a value holder on the query to obtain the object.
269
     */
269
     */
270
    protected Object valueFromRowInternalWithJoin(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException {
270
    protected Object valueFromRowInternalWithJoin(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException {
271
272
        ContainerPolicy policy = getContainerPolicy();
271
        ContainerPolicy policy = getContainerPolicy();
273
        Object value = policy.containerInstance();
272
        Object value = policy.containerInstance();
274
        ObjectBuilder objectBuilder = getDescriptor().getObjectBuilder();
273
        ObjectBuilder objectBuilder = this.descriptor.getObjectBuilder();
275
        // Extract the primary key of the source object, to filter only the joined rows for that object.
274
        // Extract the primary key of the source object, to filter only the joined rows for that object.
276
        Object sourceKey = objectBuilder.extractPrimaryKeyFromRow(row, executionSession);
275
        Object sourceKey = objectBuilder.extractPrimaryKeyFromRow(row, executionSession);
277
        CacheKey sourceCacheKey = new CacheKey(sourceKey);
278
        // If the query was using joining, all of the result rows by primary key will have been computed.
276
        // If the query was using joining, all of the result rows by primary key will have been computed.
279
        List rows = joinManager.getDataResultsByPrimaryKey().get(sourceCacheKey);
277
        List<AbstractRecord> rows = joinManager.getDataResultsByPrimaryKey().get(sourceKey);
280
        int size = rows.size();
278
        int size = rows.size();
281
        
279
        
282
        if(size > 0) {
280
        if(size > 0) {
Lines 295-301 Link Here
295
            boolean containsNull = false;
293
            boolean containsNull = false;
296
            // For each rows, extract the target row and build the target object and add to the collection.
294
            // For each rows, extract the target row and build the target object and add to the collection.
297
            for (int index = 0; index < size; index++) {
295
            for (int index = 0; index < size; index++) {
298
                AbstractRecord sourceRow = (AbstractRecord)rows.get(index);
296
                AbstractRecord sourceRow = rows.get(index);
299
                AbstractRecord targetRow = sourceRow;            
297
                AbstractRecord targetRow = sourceRow;            
300
                // The field for many objects may be in the row,
298
                // The field for many objects may be in the row,
301
                // so build the subpartion of the row through the computed values in the query,
299
                // so build the subpartion of the row through the computed values in the query,
Lines 303-311 Link Here
303
                targetRow = trimRowForJoin(targetRow, joinManager, executionSession);            
301
                targetRow = trimRowForJoin(targetRow, joinManager, executionSession);            
304
                // Partial object queries must select the primary key of the source and related objects.
302
                // Partial object queries must select the primary key of the source and related objects.
305
                // If the target joined rows in null (outerjoin) means an empty collection.
303
                // If the target joined rows in null (outerjoin) means an empty collection.
306
                Object directValue = targetRow.get(getDirectField());
304
                Object directValue = targetRow.get(this.directField);
307
                if (directValue == null) {
305
                if (directValue == null) {
308
                    if(size==1) {
306
                    if (size == 1) {
309
                        // A null direct value means an empty collection returned as nulls from an outerjoin.
307
                        // A null direct value means an empty collection returned as nulls from an outerjoin.
310
                        return getIndirectionPolicy().valueFromRow(value);
308
                        return getIndirectionPolicy().valueFromRow(value);
311
                    } else {
309
                    } else {
Lines 319-325 Link Here
319
                    if (valueConverter != null) {
317
                    if (valueConverter != null) {
320
                        directValue = valueConverter.convertDataValueToObjectValue(directValue, executionSession);
318
                        directValue = valueConverter.convertDataValueToObjectValue(directValue, executionSession);
321
                    }
319
                    }
322
                    if(shouldAddAll) {
320
                    if (shouldAddAll) {
323
                        directValuesList.add(directValue);
321
                        directValuesList.add(directValue);
324
                        targetRows.add(targetRow);
322
                        targetRows.add(targetRow);
325
                    } else {
323
                    } else {
Lines 327-340 Link Here
327
                    }
325
                    }
328
                }
326
                }
329
            }
327
            }
330
            if(shouldAddAll) {
328
            if (shouldAddAll) {
331
                // if collection contains a single element which is null then return an empty collection
329
                // if collection contains a single element which is null then return an empty collection
332
                if(!(containsNull && targetRows.size()==1)) {
330
                if (!(containsNull && targetRows.size() == 1)) {
333
                    policy.addAll(directValuesList, value, executionSession, targetRows, sourceQuery);
331
                    policy.addAll(directValuesList, value, executionSession, targetRows, sourceQuery);
334
                }
332
                }
335
            } else {
333
            } else {
336
                // if collection contains a single element which is null then return an empty collection
334
                // if collection contains a single element which is null then return an empty collection
337
                if(containsNull && policy.sizeFor(value)==1) {
335
                if (containsNull && policy.sizeFor(value) == 1) {
338
                    policy.clear(value);
336
                    policy.clear(value);
339
                }
337
                }
340
            }
338
            }
Lines 858-882 Link Here
858
     * Extract the source primary key value from the reference direct row.
856
     * Extract the source primary key value from the reference direct row.
859
     * Used for batch reading, most following same order and fields as in the mapping.
857
     * Used for batch reading, most following same order and fields as in the mapping.
860
     */
858
     */
861
    protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
859
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
862
        Vector key = new Vector(getReferenceKeyFields().size());
860
        int size = this.referenceKeyFields.size();
861
        Object[] key = new Object[size];
863
862
864
        for (int index = 0; index < getReferenceKeyFields().size(); index++) {
863
        for (int index = 0; index < size; index++) {
865
            DatabaseField relationField = getReferenceKeyFields().elementAt(index);
864
            DatabaseField relationField = this.referenceKeyFields.get(index);
866
            DatabaseField sourceField = getSourceKeyFields().elementAt(index);
865
            DatabaseField sourceField = this.sourceKeyFields.get(index);
867
            Object value = row.get(relationField);
866
            Object value = row.get(relationField);
868
867
869
            // Must ensure the classification gets a cache hit.
868
            // Must ensure the classification gets a cache hit.
870
            try {
869
            try {
871
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceField));
870
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, this.descriptor.getObjectBuilder().getFieldClassification(sourceField));
872
            } catch (ConversionException e) {
871
            } catch (ConversionException e) {
873
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
872
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
874
            }
873
            }
875
874
876
            key.addElement(value);
875
            key[index] = value;
877
        }
876
        }
878
877
879
        return key;
878
        return new CacheId(key);
880
    }
879
    }
881
880
882
    /**
881
    /**
Lines 884-907 Link Here
884
     * Extract the primary key value from the source row.
883
     * Extract the primary key value from the source row.
885
     * Used for batch reading, most following same order and fields as in the mapping.
884
     * Used for batch reading, most following same order and fields as in the mapping.
886
     */
885
     */
887
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
886
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
888
        Vector key = new Vector(getSourceKeyFields().size());
887
        int size = this.sourceKeyFields.size();
888
        Object[] key = new Object[size];
889
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
889
890
890
        for (Enumeration fieldEnum = getSourceKeyFields().elements(); fieldEnum.hasMoreElements();) {
891
        for (int index = 0; index < size; index++) {
891
            DatabaseField field = (DatabaseField)fieldEnum.nextElement();
892
            DatabaseField field = this.sourceKeyFields.get(index);
892
            Object value = row.get(field);
893
            Object value = row.get(field);
893
894
894
            // Must ensure the classification to get a cache hit.
895
            // Must ensure the classification to get a cache hit.
895
            try {
896
            try {
896
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
897
                value = conversionManager.convertObject(value, this.descriptor.getObjectBuilder().getFieldClassification(field));
897
            } catch (ConversionException e) {
898
            } catch (ConversionException e) {
898
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
899
                throw ConversionException.couldNotBeConverted(this, this.descriptor, e);
899
            }
900
            }
900
901
901
            key.addElement(value);
902
            key[index] = value;
902
        }
903
        }
903
904
        
904
        return key;
905
        return new CacheId(key);
905
    }
906
    }
906
907
907
    /**
908
    /**
Lines 910-931 Link Here
910
     */
911
     */
911
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
912
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
912
        //this can be null, because either one exists in the query or it will be created
913
        //this can be null, because either one exists in the query or it will be created
913
        Hashtable referenceDataByKey = null;
914
        Map<Object, Object> referenceDataByKey = null;
914
        ContainerPolicy mappingContainerPolicy = getContainerPolicy();
915
        ContainerPolicy mappingContainerPolicy = getContainerPolicy();
915
        synchronized (query) {
916
        synchronized (query) {
916
            referenceDataByKey = getBatchReadObjects(query, session);
917
            referenceDataByKey = getBatchReadObjects(query, session);
917
            mappingContainerPolicy = getContainerPolicy();
918
            mappingContainerPolicy = getContainerPolicy();
918
            if (referenceDataByKey == null) {
919
            if (referenceDataByKey == null) {
919
                Vector rows = (Vector)session.executeQuery(query, argumentRow);
920
                List rows = (List)session.executeQuery(query, argumentRow);
920
                int size = rows.size();
921
                int size = rows.size();
921
                referenceDataByKey = new Hashtable();
922
                referenceDataByKey = new Hashtable();
922
                if(mappingContainerPolicy.shouldAddAll()) {
923
                if (mappingContainerPolicy.shouldAddAll()) {
923
                    if(size > 0) {
924
                    if (size > 0) {
924
                        HashMap<CacheKey, List[]> referenceDataAndRowsByKey = new HashMap();
925
                        Map<Object, List[]> referenceDataAndRowsByKey = new HashMap();
925
                        for (int i=0; i < size; i++) {
926
                        for (int i = 0; i < size; i++) {
926
                            AbstractRecord referenceRow = (AbstractRecord)rows.get(i);
927
                            AbstractRecord referenceRow = (AbstractRecord)rows.get(i);
927
                            Object referenceValue = referenceRow.get(getDirectField());
928
                            Object referenceValue = referenceRow.get(getDirectField());
928
                            CacheKey eachReferenceKey = new CacheKey(extractKeyFromTargetRow(referenceRow, session));
929
                            Object eachReferenceKey = extractKeyFromTargetRow(referenceRow, session);
929
        
930
        
930
                            // Allow for value conversion.
931
                            // Allow for value conversion.
931
                            if (getValueConverter() != null) {
932
                            if (getValueConverter() != null) {
Lines 940-949 Link Here
940
                            valuesAndRows[1].add(referenceRow);
941
                            valuesAndRows[1].add(referenceRow);
941
                        }
942
                        }
942
943
943
                        Iterator<Map.Entry<CacheKey, List[]>> it = referenceDataAndRowsByKey.entrySet().iterator();
944
                        Iterator<Map.Entry<Object, List[]>> it = referenceDataAndRowsByKey.entrySet().iterator();
944
                        while(it.hasNext()) {
945
                        while(it.hasNext()) {
945
                            Map.Entry<CacheKey, List[]> entry = it.next();
946
                            Map.Entry<Object, List[]> entry = it.next();
946
                            CacheKey eachReferenceKey = entry.getKey();
947
                            Object eachReferenceKey = entry.getKey();
947
                            List referenceValues = entry.getValue()[0];
948
                            List referenceValues = entry.getValue()[0];
948
                            List<AbstractRecord> referenceRows = entry.getValue()[1];
949
                            List<AbstractRecord> referenceRows = entry.getValue()[1];
949
                            Object container = mappingContainerPolicy.containerInstance(referenceValues.size());
950
                            Object container = mappingContainerPolicy.containerInstance(referenceValues.size());
Lines 955-961 Link Here
955
                    for (int i=0; i < size; i++) {
956
                    for (int i=0; i < size; i++) {
956
                        AbstractRecord referenceRow = (AbstractRecord)rows.get(i);
957
                        AbstractRecord referenceRow = (AbstractRecord)rows.get(i);
957
                        Object referenceValue = referenceRow.get(getDirectField());
958
                        Object referenceValue = referenceRow.get(getDirectField());
958
                        CacheKey eachReferenceKey = new CacheKey(extractKeyFromTargetRow(referenceRow, session));
959
                        Object eachReferenceKey = extractKeyFromTargetRow(referenceRow, session);
959
    
960
    
960
                        Object container = referenceDataByKey.get(eachReferenceKey);
961
                        Object container = referenceDataByKey.get(eachReferenceKey);
961
                        if (container == null) {
962
                        if (container == null) {
Lines 975-981 Link Here
975
                query.setSession(null);
976
                query.setSession(null);
976
            }
977
            }
977
        }
978
        }
978
        Object result = referenceDataByKey.get(new CacheKey(extractPrimaryKeyFromRow(databaseRow, session)));
979
        Object result = referenceDataByKey.get(extractPrimaryKeyFromRow(databaseRow, session));
979
980
980
        // The source object might not have any target objects
981
        // The source object might not have any target objects
981
        if (result == null) {
982
        if (result == null) {
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/DirectMapMapping.java (-16 / +12 lines)
Lines 25-31 Link Here
25
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
25
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
26
import org.eclipse.persistence.internal.descriptors.changetracking.AttributeChangeListener;
26
import org.eclipse.persistence.internal.descriptors.changetracking.AttributeChangeListener;
27
import org.eclipse.persistence.internal.descriptors.changetracking.ObjectChangeListener;
27
import org.eclipse.persistence.internal.descriptors.changetracking.ObjectChangeListener;
28
import org.eclipse.persistence.internal.identitymaps.CacheKey;
29
import org.eclipse.persistence.internal.expressions.*;
28
import org.eclipse.persistence.internal.expressions.*;
30
import org.eclipse.persistence.internal.helper.*;
29
import org.eclipse.persistence.internal.helper.*;
31
import org.eclipse.persistence.internal.indirection.*;
30
import org.eclipse.persistence.internal.indirection.*;
Lines 391-397 Link Here
391
        ContainerPolicy cp = getContainerPolicy();
390
        ContainerPolicy cp = getContainerPolicy();
392
        for (Object iter = cp.iteratorFor(element); cp.hasNext(iter);) {
391
        for (Object iter = cp.iteratorFor(element); cp.hasNext(iter);) {
393
            Object wrappedObject = cp.nextEntry(iter, iterator.getSession());
392
            Object wrappedObject = cp.nextEntry(iter, iterator.getSession());
394
            Object object = cp.unwrapIteratorResult(wrappedObject);
395
            cp.iterateOnMapKey(iterator, wrappedObject);
393
            cp.iterateOnMapKey(iterator, wrappedObject);
396
        }
394
        }
397
    }
395
    }
Lines 945-962 Link Here
945
     */
943
     */
946
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
944
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
947
        //this can be null, because either one exists in the query or it will be created
945
        //this can be null, because either one exists in the query or it will be created
948
        Hashtable referenceDataByKey = null;
946
        Map<Object, Object> referenceDataByKey = null;
949
        ContainerPolicy mappingContainerPolicy = getContainerPolicy();
947
        ContainerPolicy mappingContainerPolicy = getContainerPolicy();
950
        synchronized (query) {
948
        synchronized (query) {
951
            referenceDataByKey = (Hashtable)query.getProperty("batched objects");
949
            referenceDataByKey = (Map)query.getProperty("batched objects");
952
            mappingContainerPolicy = getContainerPolicy();
950
            mappingContainerPolicy = getContainerPolicy();
953
            if (referenceDataByKey == null) {
951
            if (referenceDataByKey == null) {
954
                
952
                
955
                Vector rows = (Vector)session.executeQuery(query, argumentRow);
953
                List<AbstractRecord> rows = (List)session.executeQuery(query, argumentRow);
956
                referenceDataByKey = new Hashtable();
954
                referenceDataByKey = new Hashtable();
957
955
958
                for (Enumeration rowsEnum = rows.elements(); rowsEnum.hasMoreElements();) {
956
                for (AbstractRecord referenceRow : rows) {
959
                    AbstractRecord referenceRow = (AbstractRecord)rowsEnum.nextElement();
960
                    Object referenceKey = null;
957
                    Object referenceKey = null;
961
                    if (query.isObjectBuildingQuery()){
958
                    if (query.isObjectBuildingQuery()){
962
                        referenceKey = getDirectMapUsableContainerPolicy().buildKey(databaseRow, (ObjectBuildingQuery)query, session);
959
                        referenceKey = getDirectMapUsableContainerPolicy().buildKey(databaseRow, (ObjectBuildingQuery)query, session);
Lines 964-970 Link Here
964
                        referenceKey = getDirectMapUsableContainerPolicy().buildKey(databaseRow, null, session);
961
                        referenceKey = getDirectMapUsableContainerPolicy().buildKey(databaseRow, null, session);
965
                    }
962
                    }
966
                    Object referenceValue = referenceRow.get(getDirectField());
963
                    Object referenceValue = referenceRow.get(getDirectField());
967
                    CacheKey eachCacheKey = new CacheKey(extractKeyFromTargetRow(referenceRow, session));
964
                    Object eachCacheKey = extractKeyFromTargetRow(referenceRow, session);
968
965
969
                    Object container = referenceDataByKey.get(eachCacheKey);
966
                    Object container = referenceDataByKey.get(eachCacheKey);
970
                    if (container == null) {
967
                    if (container == null) {
Lines 985-991 Link Here
985
                
982
                
986
            }
983
            }
987
        }
984
        }
988
        Object result = referenceDataByKey.get(new CacheKey(extractPrimaryKeyFromRow(databaseRow, session)));
985
        Object result = referenceDataByKey.get(extractPrimaryKeyFromRow(databaseRow, session));
989
986
990
        // The source object might not have any target objects
987
        // The source object might not have any target objects
991
        if (result == null) {
988
        if (result == null) {
Lines 1006-1023 Link Here
1006
        ObjectBuilder objectBuilder = getDescriptor().getObjectBuilder();
1003
        ObjectBuilder objectBuilder = getDescriptor().getObjectBuilder();
1007
        // Extract the primary key of the source object, to filter only the joined rows for that object.
1004
        // Extract the primary key of the source object, to filter only the joined rows for that object.
1008
        Object sourceKey = objectBuilder.extractPrimaryKeyFromRow(row, executionSession);
1005
        Object sourceKey = objectBuilder.extractPrimaryKeyFromRow(row, executionSession);
1009
        CacheKey sourceCacheKey = new CacheKey(sourceKey);
1010
        // If the query was using joining, all of the result rows by primary key will have been computed.
1006
        // If the query was using joining, all of the result rows by primary key will have been computed.
1011
        List rows = joinManager.getDataResultsByPrimaryKey().get(sourceCacheKey);
1007
        List<AbstractRecord> rows = joinManager.getDataResultsByPrimaryKey().get(sourceKey);
1012
        
1008
        
1013
        // A set of direct values must be maintained to avoid duplicates from multiple 1-m joins.
1009
        // A set of direct values must be maintained to avoid duplicates from multiple 1-m joins.
1014
        Set directValues = new HashSet();
1010
        Set directValues = new HashSet();
1015
1011
1016
        Converter keyConverter = getKeyConverter();
1017
        Converter valueConverter = getValueConverter();
1012
        Converter valueConverter = getValueConverter();
1018
        // For each rows, extract the target row and build the target object and add to the collection.
1013
        // For each rows, extract the target row and build the target object and add to the collection.
1019
        for (int index = 0; index < rows.size(); index++) {
1014
        int size = rows.size();
1020
            AbstractRecord sourceRow = (AbstractRecord)rows.get(index);
1015
        for (int index = 0; index < size; index++) {
1016
            AbstractRecord sourceRow = rows.get(index);
1021
            AbstractRecord targetRow = sourceRow;            
1017
            AbstractRecord targetRow = sourceRow;            
1022
            // The field for many objects may be in the row,
1018
            // The field for many objects may be in the row,
1023
            // so build the subpartion of the row through the computed values in the query,
1019
            // so build the subpartion of the row through the computed values in the query,
Lines 1025-1031 Link Here
1025
            targetRow = trimRowForJoin(targetRow, joinManager, executionSession);
1021
            targetRow = trimRowForJoin(targetRow, joinManager, executionSession);
1026
            // Partial object queries must select the primary key of the source and related objects.
1022
            // Partial object queries must select the primary key of the source and related objects.
1027
            // If the target joined rows in null (outerjoin) means an empty collection.
1023
            // If the target joined rows in null (outerjoin) means an empty collection.
1028
            Object directKey = getContainerPolicy().buildKeyFromJoinedRow(targetRow, joinManager, sourceQuery, executionSession);
1024
            Object directKey = this.containerPolicy.buildKeyFromJoinedRow(targetRow, joinManager, sourceQuery, executionSession);
1029
            if (directKey == null) {
1025
            if (directKey == null) {
1030
                // A null direct value means an empty collection returned as nulls from an outerjoin.
1026
                // A null direct value means an empty collection returned as nulls from an outerjoin.
1031
                return getIndirectionPolicy().valueFromRow(value);
1027
                return getIndirectionPolicy().valueFromRow(value);
Lines 1033-1039 Link Here
1033
            // Only build/add the target object once, skip duplicates from multiple 1-m joins.
1029
            // Only build/add the target object once, skip duplicates from multiple 1-m joins.
1034
            if (!directValues.contains(directKey)) {
1030
            if (!directValues.contains(directKey)) {
1035
                directValues.add(directKey);
1031
                directValues.add(directKey);
1036
                Object directValue = targetRow.get(getDirectField());
1032
                Object directValue = targetRow.get(this.directField);
1037
                // Allow for value conversion.
1033
                // Allow for value conversion.
1038
                if (valueConverter != null) {
1034
                if (valueConverter != null) {
1039
                    directValue = valueConverter.convertDataValueToObjectValue(directValue, executionSession);
1035
                    directValue = valueConverter.convertDataValueToObjectValue(directValue, executionSession);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/ForeignReferenceMapping.java (-12 / +10 lines)
Lines 24-30 Link Here
24
import org.eclipse.persistence.internal.descriptors.*;
24
import org.eclipse.persistence.internal.descriptors.*;
25
import org.eclipse.persistence.internal.expressions.*;
25
import org.eclipse.persistence.internal.expressions.*;
26
import org.eclipse.persistence.internal.helper.*;
26
import org.eclipse.persistence.internal.helper.*;
27
import org.eclipse.persistence.internal.identitymaps.CacheKey;
28
import org.eclipse.persistence.internal.indirection.*;
27
import org.eclipse.persistence.internal.indirection.*;
29
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
28
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
30
import org.eclipse.persistence.internal.sessions.remote.*;
29
import org.eclipse.persistence.internal.sessions.remote.*;
Lines 550-572 Link Here
550
     * When a UnitOfWork is in transaction, it executes the batch query
549
     * When a UnitOfWork is in transaction, it executes the batch query
551
     * on the UnitOfWork and stores the clones on the UnitOfWork.
550
     * on the UnitOfWork and stores the clones on the UnitOfWork.
552
     */
551
     */
553
    protected Hashtable getBatchReadObjects(DatabaseQuery query, AbstractSession session) {
552
    protected Map getBatchReadObjects(DatabaseQuery query, AbstractSession session) {
554
        if (session.isUnitOfWork()) {
553
        if (session.isUnitOfWork()) {
555
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;
554
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;
556
            return (Hashtable)unitOfWork.getBatchReadObjects().get(query);
555
            return (Map)unitOfWork.getBatchReadObjects().get(query);
557
        } else {
556
        } else {
558
            return (Hashtable)query.getProperty("batched objects");
557
            return (Map)query.getProperty("batched objects");
559
        }
558
        }
560
    }
559
    }
561
560
562
    /**
561
    /**
563
     * INTERNAL:
562
     * INTERNAL:
564
     * The hashtable of batched objects resides in one of two places.
563
     * The map of batched objects resides in one of two places.
565
     * In the normal case it is stored in a query property.
564
     * In the normal case it is stored in a query property.
566
     * When a UnitOfWork is in transaction, it executes the batch query
565
     * When a UnitOfWork is in transaction, it executes the batch query
567
     * on the UnitOfWork and stores the clones on the UnitOfWork.
566
     * on the UnitOfWork and stores the clones on the UnitOfWork.
568
     */
567
     */
569
    protected void setBatchReadObjects(Hashtable referenceObjectsByKey, DatabaseQuery query, AbstractSession session) {
568
    protected void setBatchReadObjects(Map referenceObjectsByKey, DatabaseQuery query, AbstractSession session) {
570
        if (session.isUnitOfWork()) {
569
        if (session.isUnitOfWork()) {
571
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;
570
            UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)session;
572
            unitOfWork.getBatchReadObjects().put(query, referenceObjectsByKey);
571
            unitOfWork.getBatchReadObjects().put(query, referenceObjectsByKey);
Lines 832-838 Link Here
832
        if (isPrivateOwned){
831
        if (isPrivateOwned){
833
            getDescriptor().addMappingsPostCalculateChanges(this);
832
            getDescriptor().addMappingsPostCalculateChanges(this);
834
            if (getDescriptor().hasInheritance()){
833
            if (getDescriptor().hasInheritance()){
835
                for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
834
                for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
836
                    descriptor.addMappingsPostCalculateChanges(this);
835
                    descriptor.addMappingsPostCalculateChanges(this);
837
                }
836
                }
838
            }
837
            }
Lines 1114-1127 Link Here
1114
            if (isPrivateOwned && !this.isPrivateOwned){
1113
            if (isPrivateOwned && !this.isPrivateOwned){
1115
                this.descriptor.addMappingsPostCalculateChanges(this);
1114
                this.descriptor.addMappingsPostCalculateChanges(this);
1116
                if (getDescriptor().hasInheritance()){
1115
                if (getDescriptor().hasInheritance()){
1117
                    for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
1116
                    for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
1118
                        descriptor.addMappingsPostCalculateChanges(this);
1117
                        descriptor.addMappingsPostCalculateChanges(this);
1119
                    }
1118
                    }
1120
                }
1119
                }
1121
            }else if (!isPrivateOwned && this.isPrivateOwned){
1120
            }else if (!isPrivateOwned && this.isPrivateOwned){
1122
                this.descriptor.getMappingsPostCalculateChanges().remove(this);
1121
                this.descriptor.getMappingsPostCalculateChanges().remove(this);
1123
                if (getDescriptor().hasInheritance()){
1122
                if (getDescriptor().hasInheritance()){
1124
                    for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
1123
                    for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
1125
                        descriptor.getMappingsPostCalculateChanges().remove(this);
1124
                        descriptor.getMappingsPostCalculateChanges().remove(this);
1126
                    }
1125
                    }
1127
                }
1126
                }
Lines 1727-1735 Link Here
1727
            List nestedDataResults = dataResults;
1726
            List nestedDataResults = dataResults;
1728
            if (nestedDataResults == null) {
1727
            if (nestedDataResults == null) {
1729
                // Extract the primary key of the source object, to filter only the joined rows for that object.
1728
                // Extract the primary key of the source object, to filter only the joined rows for that object.
1730
                Object sourceKey = getDescriptor().getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession);
1729
                Object sourceKey = this.descriptor.getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession);
1731
                CacheKey sourceCacheKey = new CacheKey(sourceKey);
1730
                nestedDataResults = joinManager.getDataResultsByPrimaryKey().get(sourceKey);
1732
                nestedDataResults = joinManager.getDataResultsByPrimaryKey().get(sourceCacheKey);
1733
            }
1731
            }
1734
            nestedDataResults = new ArrayList(nestedDataResults);
1732
            nestedDataResults = new ArrayList(nestedDataResults);
1735
            Object indexObject = joinManager.getJoinedMappingIndexes_().get(this);
1733
            Object indexObject = joinManager.getJoinedMappingIndexes_().get(this);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/ManyToManyMapping.java (-14 / +18 lines)
Lines 19-24 Link Here
19
import org.eclipse.persistence.history.*;
19
import org.eclipse.persistence.history.*;
20
import org.eclipse.persistence.internal.expressions.*;
20
import org.eclipse.persistence.internal.expressions.*;
21
import org.eclipse.persistence.internal.helper.*;
21
import org.eclipse.persistence.internal.helper.*;
22
import org.eclipse.persistence.internal.identitymaps.CacheId;
22
import org.eclipse.persistence.internal.queries.*;
23
import org.eclipse.persistence.internal.queries.*;
23
import org.eclipse.persistence.internal.sessions.*;
24
import org.eclipse.persistence.internal.sessions.*;
24
import org.eclipse.persistence.mappings.foundation.MapComponentMapping;
25
import org.eclipse.persistence.mappings.foundation.MapComponentMapping;
Lines 176-185 Link Here
176
     * Extract the source primary key value from the relation row.
177
     * Extract the source primary key value from the relation row.
177
     * Used for batch reading, most following same order and fields as in the mapping.
178
     * Used for batch reading, most following same order and fields as in the mapping.
178
     */
179
     */
179
    protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
180
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
180
        Vector key = new Vector(getSourceRelationKeyFields().size());
181
        int size = getSourceRelationKeyFields().size();
182
        Object[] key = new Object[size];
181
183
182
        for (int index = 0; index < getSourceRelationKeyFields().size(); index++) {
184
        for (int index = 0; index < size; index++) {
183
            DatabaseField relationField = getSourceRelationKeyFields().elementAt(index);
185
            DatabaseField relationField = getSourceRelationKeyFields().elementAt(index);
184
            DatabaseField sourceField = getSourceKeyFields().elementAt(index);
186
            DatabaseField sourceField = getSourceKeyFields().elementAt(index);
185
            Object value = row.get(relationField);
187
            Object value = row.get(relationField);
Lines 191-200 Link Here
191
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
193
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
192
            }
194
            }
193
195
194
            key.addElement(value);
196
            key[index] = value;
195
        }
197
        }
196
198
197
        return key;
199
        return new CacheId(key);
198
    }
200
    }
199
201
200
    /**
202
    /**
Lines 202-225 Link Here
202
     * Extract the primary key value from the source row.
204
     * Extract the primary key value from the source row.
203
     * Used for batch reading, most following same order and fields as in the mapping.
205
     * Used for batch reading, most following same order and fields as in the mapping.
204
     */
206
     */
205
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
207
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
206
        Vector key = new Vector(getSourceKeyFields().size());
208
        int size = getSourceKeyFields().size();
209
        Object[] key = new Object[size];
210
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
207
211
208
        for (Enumeration fieldEnum = getSourceKeyFields().elements(); fieldEnum.hasMoreElements();) {
212
        for (int index = 0; index < size; index++) {
209
            DatabaseField field = (DatabaseField)fieldEnum.nextElement();
213
            DatabaseField field = getSourceKeyFields().get(index);
210
            Object value = row.get(field);
214
            Object value = row.get(field);
211
215
212
            // Must ensure the classification gets a cache hit.
216
            // Must ensure the classification gets a cache hit.
213
            try {
217
            try {
214
                value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
218
                value = conversionManager.convertObject(value, this.descriptor.getObjectBuilder().getFieldClassification(field));
215
            } catch (ConversionException e) {
219
            } catch (ConversionException e) {
216
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
220
                throw ConversionException.couldNotBeConverted(this, this.descriptor, e);
217
            }
221
            }
218
222
219
            key.addElement(value);
223
            key[index] = value;
220
        }
224
        }
221
225
        
222
        return key;
226
        return new CacheId(key);
223
    }
227
    }
224
228
225
    /**
229
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/ObjectReferenceMapping.java (-40 / +21 lines)
Lines 21-27 Link Here
21
import org.eclipse.persistence.indirection.ValueHolderInterface;
21
import org.eclipse.persistence.indirection.ValueHolderInterface;
22
import org.eclipse.persistence.internal.descriptors.*;
22
import org.eclipse.persistence.internal.descriptors.*;
23
import org.eclipse.persistence.internal.helper.*;
23
import org.eclipse.persistence.internal.helper.*;
24
import org.eclipse.persistence.internal.identitymaps.CacheKey;
25
import org.eclipse.persistence.internal.indirection.*;
24
import org.eclipse.persistence.internal.indirection.*;
26
import org.eclipse.persistence.internal.sessions.*;
25
import org.eclipse.persistence.internal.sessions.*;
27
import org.eclipse.persistence.queries.*;
26
import org.eclipse.persistence.queries.*;
Lines 211-231 Link Here
211
        Object firstKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstReferencedObject, session);
210
        Object firstKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstReferencedObject, session);
212
        Object secondKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondReferencedObject, session);
211
        Object secondKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondReferencedObject, session);
213
212
214
        for (int index = 0; index < ((Vector)firstKey).size(); index++) {
213
        if (firstKey == null) {
215
            Object firstValue = ((Vector)firstKey).get(index);
214
            if (secondKey == null) {
216
            Object secondValue = ((Vector)secondKey).get(index);
215
                return true;
217
218
            if (!((firstValue == null) && (secondValue == null))) {
219
                if ((firstValue == null) || (secondValue == null)) {
220
                    return false;
221
                }
222
                if (!firstValue.equals(secondValue)) {
223
                    return false;
224
                }
225
            }
216
            }
217
            return false;
226
        }
218
        }
227
219
228
        return true;
220
        return firstKey.equals(secondKey);
229
    }
221
    }
230
222
231
    /**
223
    /**
Lines 643-658 Link Here
643
    
635
    
644
            // delete the object in the database if it is no more a referenced object.						
636
            // delete the object in the database if it is no more a referenced object.						
645
            if (objectInDatabase != objectInMemory) {
637
            if (objectInDatabase != objectInMemory) {
646
                CacheKey cacheKeyForObjectInDatabase = null;
647
                CacheKey cacheKeyForObjectInMemory = new CacheKey(new Vector());
648
    
638
    
649
                cacheKeyForObjectInDatabase = new CacheKey(getPrimaryKeyForObject(objectInDatabase, query.getSession()));
639
                Object keyForObjectInDatabase = getPrimaryKeyForObject(objectInDatabase, query.getSession());
650
    
640
                Object keyForObjectInMemory = null;
651
                if (objectInMemory != null) {
641
                if (objectInMemory != null) {
652
                    cacheKeyForObjectInMemory = new CacheKey(getPrimaryKeyForObject(objectInMemory, query.getSession()));
642
                    keyForObjectInMemory = getPrimaryKeyForObject(objectInMemory, query.getSession());
653
                }
643
                }
654
    
644
    
655
                if (cacheKeysAreEqual(cacheKeyForObjectInDatabase, cacheKeyForObjectInMemory)) {
645
                if ((keyForObjectInMemory != null) && keyForObjectInDatabase.equals(keyForObjectInMemory)) {
656
                    return;
646
                    return;
657
                }
647
                }
658
            } else {
648
            } else {
Lines 684-699 Link Here
684
674
685
        // If the value was changed, both values must be deleted (uow will have inserted the new one).
675
        // If the value was changed, both values must be deleted (uow will have inserted the new one).
686
        if ((objectFromDatabase != null) && (objectFromDatabase != objectInMemory)) {
676
        if ((objectFromDatabase != null) && (objectFromDatabase != objectInMemory)) {
687
            // Also check pk as may not be maintaining identity.			
677
            // Also check pk as may not be maintaining identity.	
688
            CacheKey cacheKeyForObjectInDatabase = null;
678
            Object keyForObjectInMemory = null;
689
            CacheKey cacheKeyForObjectInMemory = new CacheKey(new Vector());
679
            Object keyForObjectInDatabase = getPrimaryKeyForObject(objectFromDatabase, query.getSession());
690
680
691
            cacheKeyForObjectInDatabase = new CacheKey(getPrimaryKeyForObject(objectFromDatabase, query.getSession()));
692
693
            if (objectInMemory != null) {
681
            if (objectInMemory != null) {
694
                cacheKeyForObjectInMemory = new CacheKey(getPrimaryKeyForObject(objectInMemory, query.getSession()));
682
                keyForObjectInMemory = getPrimaryKeyForObject(objectInMemory, query.getSession());
695
            }
683
            }
696
            if (!cacheKeysAreEqual(cacheKeyForObjectInMemory, cacheKeyForObjectInDatabase)) {
684
            if ((keyForObjectInMemory == null) || !keyForObjectInDatabase.equals(keyForObjectInMemory)) {
697
                if (objectFromDatabase != null) {
685
                if (objectFromDatabase != null) {
698
                    DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
686
                    DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
699
                    deleteQuery.setIsExecutionClone(true);
687
                    deleteQuery.setIsExecutionClone(true);
Lines 836-848 Link Here
836
            }
824
            }
837
        }
825
        }
838
    }
826
    }
839
840
    /**
841
     * INTERNAL:
842
     */
843
    protected boolean cacheKeysAreEqual(CacheKey cacheKey1, CacheKey cacheKey2) {
844
        return cacheKey1.equals(cacheKey2);
845
    }
846
    
827
    
847
    /**
828
    /**
848
     * INTERNAL:
829
     * INTERNAL:
Lines 911-922 Link Here
911
892
912
    /**
893
    /**
913
     * INTERNAL:
894
     * INTERNAL:
914
     *    Return the primary key for the reference object (i.e. the object
895
     * Return the primary key for the reference object (i.e. the object
915
     * object referenced by domainObject and specified by mapping).
896
     * object referenced by domainObject and specified by mapping).
916
     * This key will be used by a RemoteValueHolder.
897
     * This key will be used by a RemoteValueHolder.
917
     */
898
     */
918
    public Vector extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
899
    public Object extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
919
        return new Vector(1);
900
        return null;
920
    }
901
    }
921
902
922
    /**
903
    /**
Lines 925-931 Link Here
925
     */
906
     */
926
    public Object extractPrimaryKeysFromRealReferenceObject(Object object, AbstractSession session) {
907
    public Object extractPrimaryKeysFromRealReferenceObject(Object object, AbstractSession session) {
927
        if (object == null) {
908
        if (object == null) {
928
            return new Vector(1);
909
            return null;
929
        } else {
910
        } else {
930
            Object implementation = getReferenceDescriptor().getObjectBuilder().unwrapObject(object, session);
911
            Object implementation = getReferenceDescriptor().getObjectBuilder().unwrapObject(object, session);
931
            return getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(implementation, session);
912
            return getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(implementation, session);
Lines 1176-1187 Link Here
1176
     * This list may be available if the relationship has been cached.
1157
     * This list may be available if the relationship has been cached.
1177
     */
1158
     */
1178
    public Object valueFromPKList(Object[] pks, AbstractSession session) {
1159
    public Object valueFromPKList(Object[] pks, AbstractSession session) {
1179
        Vector pk = null;
1160
        Object pk = null;
1180
        if (pks[0] == null) return null;
1161
        if (pks[0] == null) return null;
1181
        if (getReferenceDescriptor().hasCMPPolicy()) {
1162
        if (getReferenceDescriptor().hasCMPPolicy()) {
1182
            pk = getReferenceDescriptor().getCMPPolicy().createPkVectorFromKey(pks[0], session);
1163
            pk = getReferenceDescriptor().getCMPPolicy().createPrimaryKeyFromId(pks[0], session);
1183
        } else {
1164
        } else {
1184
            pk = (Vector) pks[0];
1165
            pk = pks[0];
1185
        }
1166
        }
1186
        ReadObjectQuery query = new ReadObjectQuery();
1167
        ReadObjectQuery query = new ReadObjectQuery();
1187
        query.setReferenceClass(getReferenceClass());
1168
        query.setReferenceClass(getReferenceClass());
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/OneToManyMapping.java (-37 / +42 lines)
Lines 23-28 Link Here
23
import org.eclipse.persistence.queries.*;
23
import org.eclipse.persistence.queries.*;
24
import org.eclipse.persistence.sessions.DatabaseRecord;
24
import org.eclipse.persistence.sessions.DatabaseRecord;
25
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
25
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
26
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
26
import org.eclipse.persistence.internal.expressions.SQLUpdateStatement;
27
import org.eclipse.persistence.internal.expressions.SQLUpdateStatement;
27
import org.eclipse.persistence.mappings.foundation.MapComponentMapping;
28
import org.eclipse.persistence.mappings.foundation.MapComponentMapping;
28
29
Lines 295-312 Link Here
295
     * results in a hash table keyed by the (primary) keys
296
     * results in a hash table keyed by the (primary) keys
296
     * of the source objects.
297
     * of the source objects.
297
     */
298
     */
298
    protected Hashtable executeBatchQuery(DatabaseQuery query, AbstractSession session, AbstractRecord row) {
299
    protected Map executeBatchQuery(DatabaseQuery query, AbstractSession session, AbstractRecord row) {
299
        ContainerPolicy mappingCP = this.getContainerPolicy();
300
        ContainerPolicy mappingCP = getContainerPolicy();
300
        ContainerPolicy queryCP = ((ReadAllQuery)query).getContainerPolicy();
301
        ContainerPolicy queryCP = ((ReadAllQuery)query).getContainerPolicy();
301
        Object queryResult = null;
302
        Object queryResult = null;
302
303
303
        queryResult = session.executeQuery(query, row);
304
        queryResult = session.executeQuery(query, row);
304
305
305
        Hashtable batchedObjects = new Hashtable(queryCP.sizeFor(queryResult));
306
        Map batchedObjects = new Hashtable(queryCP.sizeFor(queryResult));
306
307
307
        for (Object iter = queryCP.iteratorFor(queryResult); queryCP.hasNext(iter);) {
308
        for (Object iter = queryCP.iteratorFor(queryResult); queryCP.hasNext(iter);) {
308
            Object eachReferenceObject = queryCP.next(iter, session);
309
            Object eachReferenceObject = queryCP.next(iter, session);
309
            CacheKey eachForeignKey = new CacheKey(extractForeignKeyFromReferenceObject(eachReferenceObject, session));
310
            Object eachForeignKey = extractForeignKeyFromReferenceObject(eachReferenceObject, session);
310
311
311
            Object container = batchedObjects.get(eachForeignKey);
312
            Object container = batchedObjects.get(eachForeignKey);
312
            if (container == null) {
313
            if (container == null) {
Lines 321-352 Link Here
321
    /**
322
    /**
322
     * Extract the foreign key value from the reference object.
323
     * Extract the foreign key value from the reference object.
323
     * Used for batch reading. Keep the fields in the same order
324
     * Used for batch reading. Keep the fields in the same order
324
     * as in the targetForeignKeysToSourceKeys hashtable.
325
     * as in the targetForeignKeysToSourceKeys map.
325
     */
326
     */
326
    protected Vector extractForeignKeyFromReferenceObject(Object object, AbstractSession session) {
327
    protected Object extractForeignKeyFromReferenceObject(Object object, AbstractSession session) {
327
        Vector foreignKey = new Vector(this.getTargetForeignKeysToSourceKeys().size());
328
        int size = this.sourceKeyFields.size();
329
        Object[] foreignKey = new Object[size];
330
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
331
        ObjectBuilder builder = getReferenceDescriptor().getObjectBuilder();
328
332
329
        for (Iterator stream = getTargetForeignKeysToSourceKeys().entrySet().iterator();
333
        for (int index = 0; index < size; index++) {
330
                 stream.hasNext();) {
334
            DatabaseField sourceField = this.sourceKeyFields.get(index);
331
            Map.Entry entry = (Map.Entry)stream.next();
335
            DatabaseField targetField = this.targetForeignKeyFields.get(index);
332
            DatabaseField targetField = (DatabaseField)entry.getKey();
333
            DatabaseField sourceField = (DatabaseField)entry.getValue();
334
            if (object == null) {
336
            if (object == null) {
335
                foreignKey.addElement(null);
337
                foreignKey[index] = null;
336
            } else {
338
            } else {
337
                Object value = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, targetField, session);
339
                Object value = builder.extractValueFromObjectForField(object, targetField, session);
338
340
339
                //CR:somenewsgroupbug need to ensure source and target types match.
341
                //CR:somenewsgroupbug need to ensure source and target types match.
340
                try {
342
                try {
341
                    value = session.getDatasourcePlatform().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceField));
343
                    value = conversionManager.convertObject(value, builder.getFieldClassification(sourceField));
342
                } catch (ConversionException e) {
344
                } catch (ConversionException e) {
343
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
345
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
344
                }
346
                }
345
347
346
                foreignKey.addElement(value);
348
                foreignKey[index] = value;
347
            }
349
            }
348
        }
350
        }
349
        return foreignKey;
351
        return new CacheId(foreignKey);
350
    }
352
    }
351
353
352
    /**
354
    /**
Lines 354-367 Link Here
354
     * Extract the source primary key value from the target row.
356
     * Extract the source primary key value from the target row.
355
     * Used for batch reading, most following same order and fields as in the mapping.
357
     * Used for batch reading, most following same order and fields as in the mapping.
356
     */
358
     */
357
    protected Vector extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
359
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
358
        int size = sourceKeyFields.size();
360
        int size = this.sourceKeyFields.size();
359
        Vector key = new Vector(size);
361
        Object[] key = new Object[size];
360
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
362
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
361
363
362
        for (int index = 0; index < size; index++) {
364
        for (int index = 0; index < size; index++) {
363
            DatabaseField targetField = targetForeignKeyFields.get(index);
365
            DatabaseField targetField = this.targetForeignKeyFields.get(index);
364
            DatabaseField sourceField = sourceKeyFields.get(index);
366
            DatabaseField sourceField = this.sourceKeyFields.get(index);
365
            Object value = row.get(targetField);
367
            Object value = row.get(targetField);
366
368
367
            // Must ensure the classification gets a cache hit.
369
            // Must ensure the classification gets a cache hit.
Lines 371-380 Link Here
371
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
373
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
372
            }
374
            }
373
375
374
            key.addElement(value);
376
            key[index] = value;
375
        }
377
        }
376
378
377
        return key;
379
        return new CacheId(key);
378
    }
380
    }
379
381
380
    /**
382
    /**
Lines 382-417 Link Here
382
     * Used for batch reading. Keep the fields in the same order
384
     * Used for batch reading. Keep the fields in the same order
383
     * as in the targetForeignKeysToSourceKeys hashtable.
385
     * as in the targetForeignKeysToSourceKeys hashtable.
384
     */
386
     */
385
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
387
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
386
        Vector key = new Vector(this.getTargetForeignKeysToSourceKeys().size());
388
        int size = this.sourceKeyFields.size();
389
        Object[] key = new Object[size];
390
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
387
391
388
        for (Iterator stream = getTargetForeignKeysToSourceKeys().values().iterator();
392
        for (int index = 0; index < size; index++) {
389
                 stream.hasNext();) {
393
            DatabaseField sourceField = this.sourceKeyFields.get(index);
390
            DatabaseField field = (DatabaseField)stream.next();
394
            Object value = row.get(sourceField);
391
            Object value = row.get(field);
392
395
393
            // Must ensure the classification to get a cache hit.
396
            // Must ensure the classification to get a cache hit.
394
            try {
397
            try {
395
                value = session.getDatasourcePlatform().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
398
                value = conversionManager.convertObject(value, sourceField.getType());
396
            } catch (ConversionException e) {
399
            } catch (ConversionException e) {
397
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
400
                throw ConversionException.couldNotBeConverted(this, this.descriptor, e);
398
            }
401
            }
399
402
400
            key.addElement(value);
403
            key[index] = value;
401
        }
404
        }
402
        return key;
405
        
406
        return new CacheId(key);
403
    }
407
    }
404
408
405
    /**
409
    /**
406
     * INTERNAL:
410
     * INTERNAL:
407
     * Extract the value from the batch optimized query.
411
     * Extract the value from the batch optimized query.
408
     */
412
     */
413
    @Override
409
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord row, AbstractSession session, AbstractRecord argumentRow) {
414
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord row, AbstractSession session, AbstractRecord argumentRow) {
410
        if(((ReadAllQuery)query).shouldIncludeData()) {
415
        if (((ReadAllQuery)query).shouldIncludeData()) {
411
            return super.extractResultFromBatchQuery(query, row, session, argumentRow);
416
            return super.extractResultFromBatchQuery(query, row, session, argumentRow);
412
        }
417
        }
413
        //this can be null, because either one exists in the query or it will be created
418
        //this can be null, because either one exists in the query or it will be created
414
        Hashtable batchedObjects = null;
419
        Map<Object, Object> batchedObjects = null;
415
        synchronized (query) {
420
        synchronized (query) {
416
            batchedObjects = getBatchReadObjects(query, session);
421
            batchedObjects = getBatchReadObjects(query, session);
417
            if (batchedObjects == null) {
422
            if (batchedObjects == null) {
Lines 420-426 Link Here
420
                query.setSession(null);
425
                query.setSession(null);
421
            }
426
            }
422
        }
427
        }
423
        Object result = batchedObjects.get(new CacheKey(extractPrimaryKeyFromRow(row, session)));
428
        Object result = batchedObjects.get(extractPrimaryKeyFromRow(row, session));
424
429
425
        // The source object might not have any target objects
430
        // The source object might not have any target objects
426
        if (result == null) {
431
        if (result == null) {
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/OneToOneMapping.java (-75 / +77 lines)
Lines 14-19 Link Here
14
14
15
import java.util.*;
15
import java.util.*;
16
16
17
import org.eclipse.persistence.annotations.CacheKeyType;
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.exceptions.*;
19
import org.eclipse.persistence.exceptions.*;
19
import org.eclipse.persistence.expressions.*;
20
import org.eclipse.persistence.expressions.*;
Lines 27-32 Link Here
27
import org.eclipse.persistence.queries.*;
28
import org.eclipse.persistence.queries.*;
28
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
29
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
29
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
30
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
31
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
30
import org.eclipse.persistence.internal.expressions.ConstantExpression;
32
import org.eclipse.persistence.internal.expressions.ConstantExpression;
31
import org.eclipse.persistence.internal.expressions.ObjectExpression;
33
import org.eclipse.persistence.internal.expressions.ObjectExpression;
32
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
34
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
Lines 266-277 Link Here
266
                    }
268
                    }
267
                }
269
                }
268
    
270
    
269
                Enumeration keyEnum = extractKeyFromReferenceObject(value, session).elements();
271
                Iterator keyIterator = Arrays.asList(((CacheId)extractKeyFromReferenceObject(value, session)).getPrimaryKey()).iterator();
270
                for (Iterator sourceFieldsEnum = getSourceToTargetKeyFields().keySet().iterator();
272
                for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
271
                         sourceFieldsEnum.hasNext();) {
272
                    DatabaseField field = (DatabaseField)sourceFieldsEnum.next();
273
                    Expression join = null;
273
                    Expression join = null;
274
                    join = base.getField(field).equal(keyEnum.nextElement());
274
                    join = base.getField(field).equal(keyIterator.next());
275
                    if (foreignKeyJoin == null) {
275
                    if (foreignKeyJoin == null) {
276
                        foreignKeyJoin = join;
276
                        foreignKeyJoin = join;
277
                    } else {
277
                    } else {
Lines 281-288 Link Here
281
            }
281
            }
282
        } else {
282
        } else {
283
            int size = this.mechanism.sourceKeyFields.size();
283
            int size = this.mechanism.sourceKeyFields.size();
284
            Vector keys = null;
284
            Object key = null;
285
            if(value != null) {
285
            if (value != null) {
286
                if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
286
                if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
287
                    // Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
287
                    // Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
288
                    value = ProxyIndirectionPolicy.getValueFromProxy(value);
288
                    value = ProxyIndirectionPolicy.getValueFromProxy(value);
Lines 290-313 Link Here
290
                        throw QueryException.incorrectClassForObjectComparison(base, value, this);
290
                        throw QueryException.incorrectClassForObjectComparison(base, value, this);
291
                    }
291
                    }
292
                }
292
                }
293
                keys = extractKeyFromReferenceObject(value, session);
293
                key = extractKeyFromReferenceObject(value, session);
294
                boolean allNulls = true;
294
                boolean allNulls = true;
295
                for(int i=0; i < size; i++) {
295
                for (int i=0; i < size; i++) {
296
                    if(keys.get(i) != null) {
296
                    if (((CacheId)key).getPrimaryKey()[i] != null) {
297
                        allNulls = false;
297
                        allNulls = false;
298
                        break;
298
                        break;
299
                    }
299
                    }
300
                }
300
                }
301
                // the same case
301
                // the same case
302
                if(allNulls) {
302
                if (allNulls) {
303
                    value = null;
303
                    value = null;
304
                }
304
                }
305
            }
305
            }
306
            if(value != null) {
306
            if (value != null) {
307
                for(int i=0; i < size; i++) {
307
                for(int i=0; i < size; i++) {
308
                    DatabaseField field = this.mechanism.sourceKeyFields.get(i);
308
                    DatabaseField field = this.mechanism.sourceKeyFields.get(i);
309
                    Expression join = null;
309
                    Expression join = null;
310
                    join = base.getField(field).equal(keys.get(i));
310
                    join = base.getField(field).equal(((CacheId)key).getPrimaryKey()[i]);
311
                    if (foreignKeyJoin == null) {
311
                    if (foreignKeyJoin == null) {
312
                        foreignKeyJoin = join;
312
                        foreignKeyJoin = join;
313
                    } else {
313
                    } else {
Lines 547-590 Link Here
547
     * INTERNAL:
547
     * INTERNAL:
548
     * Extract the foreign key value from the source row.
548
     * Extract the foreign key value from the source row.
549
     */
549
     */
550
    protected Vector extractForeignKeyFromRow(AbstractRecord row, AbstractSession session) {
550
    protected Object extractForeignKeyFromRow(AbstractRecord row, AbstractSession session) {
551
        Vector key;
551
        Object[] key;
552
552
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
553
        if(this.mechanism == null) {
553
        ObjectBuilder builder = this.descriptor.getObjectBuilder();
554
            key = new Vector();
554
        if (this.mechanism == null) {
555
            for (Iterator fieldEnum = getSourceToTargetKeyFields().keySet().iterator();
555
            key = new Object[getSourceToTargetKeyFields().size()];
556
                     fieldEnum.hasNext();) {
556
            int index = 0;
557
                DatabaseField field = (DatabaseField)fieldEnum.next();
557
            for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
558
                Object value = row.get(field);
558
                Object value = row.get(field);    
559
    
560
                // Must ensure the classification gets a cache hit.
559
                // Must ensure the classification gets a cache hit.
561
                try {
560
                try {
562
                    value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
561
                    value = conversionManager.convertObject(value, builder.getFieldClassification(field));
563
                } catch (ConversionException e) {
562
                } catch (ConversionException e) {
564
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
563
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
565
                }
564
                }
566
    
565
    
567
                key.addElement(value);
566
                key[index] = value;
567
                index++;
568
            }
568
            }
569
        } else {
569
        } else {
570
            int size = mechanism.sourceKeyFields.size();
570
            List<DatabaseField> sourceKeyFields = this.mechanism.sourceKeyFields;
571
            key = new Vector(size);
571
            int size = sourceKeyFields.size();
572
            for(int i=0; i < size; i++) {                
572
            key = new Object[size];
573
                DatabaseField field = mechanism.sourceKeyFields.get(i);
573
            for (int i = 0; i < size; i++) {                
574
                Object value = row.get(field);
574
                DatabaseField field = sourceKeyFields.get(i);
575
                
575
                Object value = row.get(field);                
576
                // Must ensure the classification gets a cache hit.
576
                // Must ensure the classification gets a cache hit.
577
                try {
577
                try {
578
                    value = session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
578
                    value = conversionManager.convertObject(value, builder.getFieldClassification(field));
579
                } catch (ConversionException e) {
579
                } catch (ConversionException e) {
580
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
580
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
581
                }
581
                }
582
    
582
    
583
                key.addElement(value);
583
                key[i] = value;
584
            }            
584
            }            
585
        }
585
        }
586
586
587
        return key;
587
        return new CacheId(key);
588
    }
588
    }
589
589
590
    
590
    
Lines 608-661 Link Here
608
     * INTERNAL:
608
     * INTERNAL:
609
     * Extract the key value from the reference object.
609
     * Extract the key value from the reference object.
610
     */
610
     */
611
    protected Vector extractKeyFromReferenceObject(Object object, AbstractSession session) {
611
    protected Object extractKeyFromReferenceObject(Object object, AbstractSession session) {
612
        Vector key;
612
        ObjectBuilder objectBuilder = getReferenceDescriptor().getObjectBuilder();
613
613
        Object[] key;
614
        if(this.mechanism == null) {
614
        if (this.mechanism == null) {
615
            key = new Vector();
615
            key = new Object[getSourceToTargetKeyFields().size()];
616
            for (Iterator fieldEnum = getSourceToTargetKeyFields().values().iterator();
616
            int index = 0;
617
                     fieldEnum.hasNext();) {
617
            for (DatabaseField field : getSourceToTargetKeyFields().values()) {
618
                if (object == null) {
618
                if (object == null) {
619
                    key.addElement(null);
619
                    key[index] = null;
620
                } else {
620
                } else {
621
                    DatabaseField field = (DatabaseField)fieldEnum.next();
621
                    key[index] = objectBuilder.extractValueFromObjectForField(object, field, session);
622
                    key.addElement(getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, field, session));
623
                }
622
                }
623
                index++;
624
            }
624
            }
625
        } else {
625
        } else {
626
            int size = mechanism.targetKeyFields.size();
626
            int size = this.mechanism.targetKeyFields.size();
627
            key = new Vector(size);
627
            key = new Object[size];
628
            for(int i=0; i < size; i++) {                
628
            for (int i = 0; i < size; i++) {
629
                if (object == null) {
629
                if (object == null) {
630
                    key.addElement(null);
630
                    key[i] = null;
631
                } else {
631
                } else {
632
                    DatabaseField field = mechanism.targetKeyFields.get(i);
632
                    DatabaseField field = this.mechanism.targetKeyFields.get(i);
633
                    key.addElement(getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, field, session));
633
                    key[i] = objectBuilder.extractValueFromObjectForField(object, field, session);
634
                }
634
                }
635
            }            
635
            }            
636
        }
636
        }
637
637
638
        return key;
638
        return new CacheId(key);
639
    }
639
    }
640
640
641
    /**
641
    /**
642
     * INTERNAL:
642
     * INTERNAL:
643
     *    Return the primary key for the reference object (i.e. the object
643
     * Return the primary key for the reference object (i.e. the object
644
     * object referenced by domainObject and specified by mapping).
644
     * object referenced by domainObject and specified by mapping).
645
     * This key will be used by a RemoteValueHolder.
645
     * This key will be used by a RemoteValueHolder.
646
     */
646
     */
647
    public Vector extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
647
    @Override
648
    public Object extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
648
        List primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
649
        List primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
649
        Vector result = new Vector(primaryKeyFields.size());
650
        Object[] result = new  Object[primaryKeyFields.size()];
650
        for (int index = 0; index < primaryKeyFields.size(); index++) {
651
        for (int index = 0; index < primaryKeyFields.size(); index++) {
651
            DatabaseField targetKeyField = (DatabaseField)primaryKeyFields.get(index);
652
            DatabaseField targetKeyField = (DatabaseField)primaryKeyFields.get(index);
652
            DatabaseField sourceKeyField = getTargetToSourceKeyFields().get(targetKeyField);
653
            DatabaseField sourceKeyField = getTargetToSourceKeyFields().get(targetKeyField);
653
            if (sourceKeyField == null) {
654
            if (sourceKeyField == null) {
654
                return new Vector(1);
655
                return null;
655
            }
656
            }
656
            result.addElement(row.get(sourceKeyField));
657
            result[index] = row.get(sourceKeyField);
658
            if (getReferenceDescriptor().getCacheKeyType() == CacheKeyType.ID_VALUE) {
659
                return result[index];
660
            }
657
        }
661
        }
658
        return result;
662
        return new CacheId(result);
659
    }
663
    }
660
664
661
    /**
665
    /**
Lines 682-720 Link Here
682
     */
686
     */
683
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
687
    public Object extractResultFromBatchQuery(DatabaseQuery query, AbstractRecord databaseRow, AbstractSession session, AbstractRecord argumentRow) {
684
        //this can be null, because either one exists in the query or it will be created
688
        //this can be null, because either one exists in the query or it will be created
685
        Hashtable referenceObjectsByKey = null;
689
        Map<Object, Object> referenceObjectsByKey = null;
686
        synchronized (query) {
690
        synchronized (query) {
687
            referenceObjectsByKey = getBatchReadObjects(query, session);
691
            referenceObjectsByKey = getBatchReadObjects(query, session);
688
            if (referenceObjectsByKey == null) {
692
            if (referenceObjectsByKey == null) {
689
                Vector results;
693
                List results;
690
                referenceObjectsByKey = new Hashtable();
694
                referenceObjectsByKey = new Hashtable();
691
                if(this.mechanism == null) {
695
                if (this.mechanism == null) {
692
                    results = (Vector)session.executeQuery(query, argumentRow);
696
                    results = (List)session.executeQuery(query, argumentRow);
693
    
697
    
694
                    for (Enumeration enumeration = results.elements(); enumeration.hasMoreElements();) {
698
                    for (Object eachReferenceObject : results) {
695
                        Object eachReferenceObject = enumeration.nextElement();
699
                        Object eachReferenceKey = extractKeyFromReferenceObject(eachReferenceObject, session);    
696
                        CacheKey eachReferenceKey = new CacheKey(extractKeyFromReferenceObject(eachReferenceObject, session));
697
    
698
                        referenceObjectsByKey.put(eachReferenceKey, session.wrapObject(eachReferenceObject));
700
                        referenceObjectsByKey.put(eachReferenceKey, session.wrapObject(eachReferenceObject));
699
                    }
701
                    }
700
                } else {
702
                } else {
703
                    ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
701
                    ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(query, argumentRow);
704
                    ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(query, argumentRow);
702
                    results = (Vector)complexResult.getResult();
705
                    results = (List)complexResult.getResult();
703
                    List<AbstractRecord> rows = (List)complexResult.getData();
706
                    List<AbstractRecord> rows = (List)complexResult.getData();
704
                    int size = results.size();
707
                    int size = results.size();
705
                    int sourceSize = this.mechanism.getSourceKeyFields().size();
708
                    List<DatabaseField> sourceKeyFields = this.mechanism.getSourceRelationKeyFields();
706
                    for(int i=0; i < size; i++) {
709
                    int sourceSize = sourceKeyFields.size();
710
                    for (int i=0; i < size; i++) {
707
                        AbstractRecord row = rows.get(i);
711
                        AbstractRecord row = rows.get(i);
708
                        Vector key = new Vector();
712
                        Object[] key = new Object[sourceSize];
709
                        for (int k = 0; k < sourceSize; k++) {
713
                        for (int k = 0; k < sourceSize; k++) {
710
                            Object value = row.get(this.mechanism.getSourceRelationKeyFields().get(k));
714
                            Object value = row.get(sourceKeyFields.get(k));
711
                            // must do the same conversion as extractForeignKeyFromRow does 
715
                            // must do the same conversion as extractForeignKeyFromRow does 
712
                            // so that CacheKey created here and in extractForeignKeyFromRow compare correctly. 
716
                            // so that CacheKey created here and in extractForeignKeyFromRow compare correctly. 
713
                            key.add(session.getDatasourcePlatform().getConversionManager().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(this.mechanism.getSourceKeyFields().get(k))));
717
                            key[k] = conversionManager.convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceKeyFields.get(k)));
714
                        }
718
                        }
715
                        CacheKey eachReferenceKey = new CacheKey(key);
719
                        referenceObjectsByKey.put(new CacheId(key), session.wrapObject(results.get(i)));
716
                        
717
                        referenceObjectsByKey.put(eachReferenceKey, session.wrapObject(results.get(i)));
718
                    }
720
                    }
719
                }
721
                }
720
                setBatchReadObjects(referenceObjectsByKey, query, session);
722
                setBatchReadObjects(referenceObjectsByKey, query, session);
Lines 722-728 Link Here
722
            }
724
            }
723
        }
725
        }
724
726
725
        return referenceObjectsByKey.get(new CacheKey(extractForeignKeyFromRow(databaseRow, session)));
727
        return referenceObjectsByKey.get(extractForeignKeyFromRow(databaseRow, session));
726
    }
728
    }
727
729
728
    
730
    
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/UnidirectionalOneToManyMapping.java (-9 / +9 lines)
Lines 13-19 Link Here
13
package org.eclipse.persistence.mappings;
13
package org.eclipse.persistence.mappings;
14
14
15
import java.util.Iterator;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Vector;
16
import java.util.Vector;
18
17
19
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.descriptors.ClassDescriptor;
Lines 24-29 Link Here
24
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
23
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
25
import org.eclipse.persistence.internal.helper.ConversionManager;
24
import org.eclipse.persistence.internal.helper.ConversionManager;
26
import org.eclipse.persistence.internal.helper.DatabaseField;
25
import org.eclipse.persistence.internal.helper.DatabaseField;
26
import org.eclipse.persistence.internal.identitymaps.CacheId;
27
import org.eclipse.persistence.internal.sessions.AbstractRecord;
27
import org.eclipse.persistence.internal.sessions.AbstractRecord;
28
import org.eclipse.persistence.internal.sessions.AbstractSession;
28
import org.eclipse.persistence.internal.sessions.AbstractSession;
29
import org.eclipse.persistence.internal.sessions.ChangeRecord;
29
import org.eclipse.persistence.internal.sessions.ChangeRecord;
Lines 106-114 Link Here
106
     * Extract the primary key value from the source row.
106
     * Extract the primary key value from the source row.
107
     * Used for batch reading, most following same order and fields as in the mapping.
107
     * Used for batch reading, most following same order and fields as in the mapping.
108
     */
108
     */
109
    protected Vector extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {
109
    protected Object extractPrimaryKeyFromRow(AbstractRecord row, AbstractSession session) {            
110
        int size = sourceKeyFields.size();
110
        int size = this.sourceKeyFields.size();
111
        Vector key = new Vector(size);
111
        Object[] key = new Object[size];
112
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
112
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
113
113
114
        for (int index=0; index < size; index++) {
114
        for (int index=0; index < size; index++) {
Lines 122-131 Link Here
122
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
122
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
123
            }
123
            }
124
124
125
            key.addElement(value);
125
            key[index] = value;
126
        }
126
        }
127
127
        
128
        return key;
128
        return new CacheId(key);
129
    }
129
    }
130
130
131
    /**
131
    /**
Lines 180-186 Link Here
180
            if(shouldIncrementTargetLockValueOnAddOrRemoveTarget) {
180
            if(shouldIncrementTargetLockValueOnAddOrRemoveTarget) {
181
                descriptor.addMappingsPostCalculateChanges(this);
181
                descriptor.addMappingsPostCalculateChanges(this);
182
                if (getDescriptor().hasInheritance()){
182
                if (getDescriptor().hasInheritance()){
183
                    for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
183
                    for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
184
                        descriptor.addMappingsPostCalculateChanges(this);
184
                        descriptor.addMappingsPostCalculateChanges(this);
185
                    }
185
                    }
186
                }
186
                }
Lines 188-194 Link Here
188
            if(shouldIncrementTargetLockValueOnDeleteSource && !isPrivateOwned) {
188
            if(shouldIncrementTargetLockValueOnDeleteSource && !isPrivateOwned) {
189
                descriptor.addMappingsPostCalculateChangesOnDeleted(this);
189
                descriptor.addMappingsPostCalculateChangesOnDeleted(this);
190
                if (getDescriptor().hasInheritance()){
190
                if (getDescriptor().hasInheritance()){
191
                    for (ClassDescriptor descriptor: (List<ClassDescriptor>)getDescriptor().getInheritancePolicy().getAllChildDescriptors()){
191
                    for (ClassDescriptor descriptor: getDescriptor().getInheritancePolicy().getAllChildDescriptors()) {
192
                        descriptor.addMappingsPostCalculateChangesOnDeleted(this);
192
                        descriptor.addMappingsPostCalculateChangesOnDeleted(this);
193
                    }
193
                    }
194
                }
194
                }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/VariableOneToOneMapping.java (-8 lines)
Lines 20-26 Link Here
20
import org.eclipse.persistence.exceptions.*;
20
import org.eclipse.persistence.exceptions.*;
21
import org.eclipse.persistence.expressions.*;
21
import org.eclipse.persistence.expressions.*;
22
import org.eclipse.persistence.internal.helper.*;
22
import org.eclipse.persistence.internal.helper.*;
23
import org.eclipse.persistence.internal.identitymaps.CacheKey;
24
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
23
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
25
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
24
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
26
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
25
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
Lines 538-550 Link Here
538
    /**
537
    /**
539
     * INTERNAL:
538
     * INTERNAL:
540
     */
539
     */
541
    protected boolean cacheKeysAreEqual(CacheKey cacheKey1, CacheKey cacheKey2) {
542
        return (cacheKey1.equals(cacheKey2) && (cacheKey2.getClass().equals(cacheKey1.getClass())));
543
    }
544
545
    /**
546
     * INTERNAL:
547
     */
548
    @Override
540
    @Override
549
    protected Object getPrimaryKeyForObject(Object object, AbstractSession session) {
541
    protected Object getPrimaryKeyForObject(Object object, AbstractSession session) {
550
        return session.getId(object);
542
        return session.getId(object);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/oxm/mappings/XMLCollectionReferenceMapping.java (-11 / +8 lines)
Lines 26-31 Link Here
26
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
26
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
27
import org.eclipse.persistence.internal.helper.DatabaseField;
27
import org.eclipse.persistence.internal.helper.DatabaseField;
28
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
28
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
29
import org.eclipse.persistence.internal.identitymaps.CacheId;
29
import org.eclipse.persistence.internal.oxm.Reference;
30
import org.eclipse.persistence.internal.oxm.Reference;
30
import org.eclipse.persistence.internal.oxm.ReferenceResolver;
31
import org.eclipse.persistence.internal.oxm.ReferenceResolver;
31
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
32
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
Lines 129-135 Link Here
129
        if (idx == -1) {
130
        if (idx == -1) {
130
            return null;
131
            return null;
131
        }
132
        }
132
        return ((Vector)pks).get(idx);
133
        return ((CacheId)pks).getPrimaryKey()[idx];
133
    }
134
    }
134
135
135
    /**
136
    /**
Lines 161-174 Link Here
161
        XMLField tgtFld = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlField);
162
        XMLField tgtFld = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlField);
162
        String tgtXPath = tgtFld.getXPath();        
163
        String tgtXPath = tgtFld.getXPath();        
163
        HashMap primaryKeyMap = reference.getPrimaryKeyMap();
164
        HashMap primaryKeyMap = reference.getPrimaryKeyMap();
164
        Vector pks = (Vector) primaryKeyMap.get(tgtXPath);
165
        CacheId pks = (CacheId) primaryKeyMap.get(tgtXPath);
165
        if(pks == null){
166
        ClassDescriptor descriptor = session.getClassDescriptor(getReferenceClass());
166
            pks = new Vector();
167
        if (pks == null){
168
            pks = new CacheId(new Object[0]);
167
            primaryKeyMap.put(tgtXPath, pks);
169
            primaryKeyMap.put(tgtXPath, pks);
168
        }        
170
        }        
169
171
170
        ClassDescriptor descriptor = session.getClassDescriptor(getReferenceClass());
171
        DatabaseField typedField = descriptor.getTypedField(tgtFld);
172
        Class type = descriptor.getTypedField(tgtFld).getType();
172
        Class type = descriptor.getTypedField(tgtFld).getType();
173
        XMLConversionManager xmlConversionManager = (XMLConversionManager) session.getDatasourcePlatform().getConversionManager();
173
        XMLConversionManager xmlConversionManager = (XMLConversionManager) session.getDatasourcePlatform().getConversionManager();
174
        for (StringTokenizer stok = new StringTokenizer((String) object); stok.hasMoreTokens();) {
174
        for (StringTokenizer stok = new StringTokenizer((String) object); stok.hasMoreTokens();) {
Lines 227-236 Link Here
227
     */
227
     */
228
    public Object readFromRowIntoObject(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object targetObject, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException {
228
    public Object readFromRowIntoObject(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object targetObject, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException {
229
        ClassDescriptor descriptor = sourceQuery.getSession().getClassDescriptor(getReferenceClass());
229
        ClassDescriptor descriptor = sourceQuery.getSession().getClassDescriptor(getReferenceClass());
230
        ContainerPolicy cp = this.getContainerPolicy();
230
        ContainerPolicy cp = getContainerPolicy();
231
        Vector pkFieldNames = referenceDescriptor.getPrimaryKeyFieldNames();
232
        Vector primaryKeyValues = new Vector();
233
        primaryKeyValues.setSize(pkFieldNames.size());
234
        HashMap primaryKeyMap = new HashMap();
231
        HashMap primaryKeyMap = new HashMap();
235
        // for each source xmlField, get the value from the row and store
232
        // for each source xmlField, get the value from the row and store
236
        for (Iterator fieldIt = getFields().iterator(); fieldIt.hasNext();) {
233
        for (Iterator fieldIt = getFields().iterator(); fieldIt.hasNext();) {
Lines 244-250 Link Here
244
            // need to get the actual type of the target (i.e. int, String, etc.) 
241
            // need to get the actual type of the target (i.e. int, String, etc.) 
245
            // and use the converted value when checking the cache.
242
            // and use the converted value when checking the cache.
246
            XMLConversionManager xmlConversionManager = (XMLConversionManager) executionSession.getDatasourcePlatform().getConversionManager();
243
            XMLConversionManager xmlConversionManager = (XMLConversionManager) executionSession.getDatasourcePlatform().getConversionManager();
247
            Vector newValues = new Vector();
244
            CacheId newValues = new CacheId(new Object[0]);
248
            for (Iterator valIt = ((Vector) fieldValue).iterator(); valIt.hasNext();) {
245
            for (Iterator valIt = ((Vector) fieldValue).iterator(); valIt.hasNext();) {
249
                for (StringTokenizer stok = new StringTokenizer((String) valIt.next()); stok.hasMoreTokens();) {
246
                for (StringTokenizer stok = new StringTokenizer((String) valIt.next()); stok.hasMoreTokens();) {
250
                    Object value = xmlConversionManager.convertObject(stok.nextToken(), descriptor.getTypedField(tgtFld).getType());
247
                    Object value = xmlConversionManager.convertObject(stok.nextToken(), descriptor.getTypedField(tgtFld).getType());
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/oxm/mappings/XMLObjectReferenceMapping.java (-8 / +7 lines)
Lines 23-28 Link Here
23
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
23
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
24
import org.eclipse.persistence.internal.helper.ClassConstants;
24
import org.eclipse.persistence.internal.helper.ClassConstants;
25
import org.eclipse.persistence.internal.helper.DatabaseField;
25
import org.eclipse.persistence.internal.helper.DatabaseField;
26
import org.eclipse.persistence.internal.identitymaps.CacheId;
26
import org.eclipse.persistence.internal.oxm.Reference;
27
import org.eclipse.persistence.internal.oxm.Reference;
27
import org.eclipse.persistence.internal.oxm.ReferenceListener;
28
import org.eclipse.persistence.internal.oxm.ReferenceListener;
28
import org.eclipse.persistence.internal.oxm.ReferenceResolver;
29
import org.eclipse.persistence.internal.oxm.ReferenceResolver;
Lines 103-109 Link Here
103
        if (idx == -1) {
104
        if (idx == -1) {
104
            return null;
105
            return null;
105
        }
106
        }
106
        return ((Vector)pks).get(idx);
107
        return ((CacheId)pks).getPrimaryKey()[idx];
107
    }
108
    }
108
109
109
    /**
110
    /**
Lines 133-153 Link Here
133
        // if reference is null, create a new instance and set it on the resolver
134
        // if reference is null, create a new instance and set it on the resolver
134
        Reference reference = resolver.getReference(this, srcObject);
135
        Reference reference = resolver.getReference(this, srcObject);
135
        if (reference == null) {
136
        if (reference == null) {
136
            Vector pks = new Vector();
137
            CacheId pks = new CacheId(new Object[pkFieldNames.size()]);
137
            pks.setSize(pkFieldNames.size());
138
            reference = new Reference(this, srcObject, getReferenceClass(), pks);
138
            reference = new Reference(this, srcObject, getReferenceClass(), pks);
139
            resolver.addReference(reference);
139
            resolver.addReference(reference);
140
            record.reference(reference);
140
            record.reference(reference);
141
        }
141
        }
142
        XMLField tgtFld = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlField);
142
        XMLField tgtFld = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlField);
143
        int idx = pkFieldNames.indexOf(tgtFld.getXPath());
143
        int idx = pkFieldNames.indexOf(tgtFld.getXPath());
144
        Vector primaryKeys = reference.getPrimaryKeys();
144
        Object primaryKeys = reference.getPrimaryKey();
145
        // fix for bug# 5687430
145
        // fix for bug# 5687430
146
        // need to get the actual type of the target (i.e. int, String, etc.) 
146
        // need to get the actual type of the target (i.e. int, String, etc.) 
147
        // and use the converted value when checking the cache.
147
        // and use the converted value when checking the cache.
148
        Object value = session.getDatasourcePlatform().getConversionManager().convertObject(object, clsDescriptor.getTypedField(tgtFld).getType());
148
        Object value = session.getDatasourcePlatform().getConversionManager().convertObject(object, clsDescriptor.getTypedField(tgtFld).getType());
149
        if (value != null) {
149
        if (value != null) {
150
            primaryKeys.setElementAt(value, idx);
150
            ((CacheId)primaryKeys).set(idx, value);
151
        }
151
        }
152
    }
152
    }
153
153
Lines 342-349 Link Here
342
        // reference descriptor's primary key entries
342
        // reference descriptor's primary key entries
343
        ClassDescriptor descriptor = sourceQuery.getSession().getClassDescriptor(getReferenceClass());
343
        ClassDescriptor descriptor = sourceQuery.getSession().getClassDescriptor(getReferenceClass());
344
        Vector pkFieldNames = descriptor.getPrimaryKeyFieldNames();
344
        Vector pkFieldNames = descriptor.getPrimaryKeyFieldNames();
345
        Vector primaryKeys = new Vector();
345
        CacheId primaryKeys = new CacheId(new Object[pkFieldNames.size()]);
346
        primaryKeys.setSize(pkFieldNames.size());
347
        Iterator keyIt = sourceToTargetKeys.iterator();
346
        Iterator keyIt = sourceToTargetKeys.iterator();
348
        while (keyIt.hasNext()) {
347
        while (keyIt.hasNext()) {
349
            XMLField keyFld = (XMLField) keyIt.next();
348
            XMLField keyFld = (XMLField) keyIt.next();
Lines 357-363 Link Here
357
            // and use the converted value when checking the cache.
356
            // and use the converted value when checking the cache.
358
            Object value = executionSession.getDatasourcePlatform().getConversionManager().convertObject(databaseRow.get(keyFld), descriptor.getTypedField(tgtFld).getType());
357
            Object value = executionSession.getDatasourcePlatform().getConversionManager().convertObject(databaseRow.get(keyFld), descriptor.getTypedField(tgtFld).getType());
359
            if (value != null) {
358
            if (value != null) {
360
                primaryKeys.setElementAt(value, idx);
359
                primaryKeys.set(idx, value);
361
            }
360
            }
362
        }
361
        }
363
        // store the Reference instance on the resolver for use during mapping
362
        // store the Reference instance on the resolver for use during mapping
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/oxm/record/UnmarshalRecord.java (-7 / +6 lines)
Lines 17-23 Link Here
17
import java.util.HashMap;
17
import java.util.HashMap;
18
import java.util.List;
18
import java.util.List;
19
import java.util.Map;
19
import java.util.Map;
20
import java.util.Vector;
21
20
22
import javax.xml.namespace.QName;
21
import javax.xml.namespace.QName;
23
22
Lines 28-33 Link Here
28
import org.eclipse.persistence.exceptions.XMLMarshalException;
27
import org.eclipse.persistence.exceptions.XMLMarshalException;
29
import org.eclipse.persistence.internal.helper.DatabaseField;
28
import org.eclipse.persistence.internal.helper.DatabaseField;
30
import org.eclipse.persistence.internal.helper.Helper;
29
import org.eclipse.persistence.internal.helper.Helper;
30
import org.eclipse.persistence.internal.identitymaps.CacheId;
31
import org.eclipse.persistence.internal.identitymaps.CacheKey;
31
import org.eclipse.persistence.internal.identitymaps.CacheKey;
32
import org.eclipse.persistence.internal.oxm.ContainerValue;
32
import org.eclipse.persistence.internal.oxm.ContainerValue;
33
import org.eclipse.persistence.internal.oxm.NodeValue;
33
import org.eclipse.persistence.internal.oxm.NodeValue;
Lines 520-531 Link Here
520
                int primaryKeyFieldsSize = primaryKeyFields.size();
520
                int primaryKeyFieldsSize = primaryKeyFields.size();
521
                if (primaryKeyFieldsSize > 0) {
521
                if (primaryKeyFieldsSize > 0) {
522
                    Object pk = treeObjectBuilder.extractPrimaryKeyFromObject(currentObject, session);
522
                    Object pk = treeObjectBuilder.extractPrimaryKeyFromObject(currentObject, session);
523
                    if (((Vector)pk).contains(null)) {
523
                    for (int x=0; x<primaryKeyFieldsSize; x++) {
524
                        for (int x=0; x<primaryKeyFieldsSize; x++) {
524
                        Object value = ((CacheId)pk).getPrimaryKey()[x];
525
                            if (null == ((Vector)pk).get(x)) {
525
                        if (null == value) {
526
                                XMLField pkField = (XMLField) xmlDescriptor.getPrimaryKeyFields().get(x);
526
                            XMLField pkField = (XMLField) xmlDescriptor.getPrimaryKeyFields().get(x);
527
                                ((Vector)pk).set(x, getUnmarshaller().getXMLContext().getValueByXPath(currentObject, pkField.getXPath(), pkField.getNamespaceResolver(), Object.class));
527
                            ((CacheId)pk).set(x, getUnmarshaller().getXMLContext().getValueByXPath(currentObject, pkField.getXPath(), pkField.getNamespaceResolver(), Object.class));
528
                            }
529
                        }
528
                        }
530
                    }
529
                    }
531
                    CacheKey key = session.getIdentityMapAccessorInstance().acquireDeferredLock(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
530
                    CacheKey key = session.getIdentityMapAccessorInstance().acquireDeferredLock(pk, xmlDescriptor.getJavaClass(), xmlDescriptor);
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/oxm/XMLDescriptor.java (-5 / +3 lines)
Lines 509-523 Link Here
509
        // Make sure that child is post initialized,
509
        // Make sure that child is post initialized,
510
        // this initialize bottom up, unlike the two other phases that to top down.
510
        // this initialize bottom up, unlike the two other phases that to top down.
511
        if (hasInheritance()) {
511
        if (hasInheritance()) {
512
            for (Enumeration childEnum = getInheritancePolicy().getChildDescriptors().elements(); childEnum.hasMoreElements();) {
512
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
513
                ((ClassDescriptor) childEnum.nextElement()).postInitialize(session);
513
                child.postInitialize(session);
514
            }
514
            }
515
        }
515
        }
516
516
517
        // Allow mapping to perform post initialization.
517
        // Allow mapping to perform post initialization.
518
        for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
518
        for (DatabaseMapping mapping : getMappings()) {
519
            DatabaseMapping mapping = (DatabaseMapping) mappingsEnum.nextElement();
520
521
            // This causes post init to be called multiple times in inheritance.
519
            // This causes post init to be called multiple times in inheritance.
522
            mapping.postInitialize(session);
520
            mapping.postInitialize(session);
523
        }
521
        }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DoesExistQuery.java (-2 / +1 lines)
Lines 12-18 Link Here
12
 ******************************************************************************/  
12
 ******************************************************************************/  
13
package org.eclipse.persistence.queries;
13
package org.eclipse.persistence.queries;
14
14
15
import java.util.*;
16
import org.eclipse.persistence.descriptors.ClassDescriptor;
15
import org.eclipse.persistence.descriptors.ClassDescriptor;
17
import org.eclipse.persistence.exceptions.*;
16
import org.eclipse.persistence.exceptions.*;
18
import org.eclipse.persistence.internal.helper.*;
17
import org.eclipse.persistence.internal.helper.*;
Lines 149-155 Link Here
149
            }
148
            }
150
                
149
                
151
        }
150
        }
152
        if ((primaryKey == null) || (((Vector)primaryKey).contains(null))) {
151
        if (primaryKey == null) {
153
            return Boolean.FALSE;
152
            return Boolean.FALSE;
154
        }
153
        }
155
        
154
        
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectBuildingQuery.java (-46 lines)
Lines 53-61 Link Here
53
    /** INTERNAL: for bug 2612601 allow ability not to register results in UOW. */
53
    /** INTERNAL: for bug 2612601 allow ability not to register results in UOW. */
54
    protected boolean shouldRegisterResultsInUnitOfWork = true;
54
    protected boolean shouldRegisterResultsInUnitOfWork = true;
55
55
56
    /** CMP only. Allow users to configure whether finder should be executed in a uow or not. */
57
    protected boolean shouldProcessResultsInUnitOfWork = true;
58
59
    /** Used for pessimistic locking. */
56
    /** Used for pessimistic locking. */
60
    protected ForUpdateClause lockingClause;
57
    protected ForUpdateClause lockingClause;
61
    public static final short NO_LOCK = 0;
58
    public static final short NO_LOCK = 0;
Lines 163-169 Link Here
163
        if (query.isObjectBuildingQuery()) {
160
        if (query.isObjectBuildingQuery()) {
164
            ObjectBuildingQuery readQuery = (ObjectBuildingQuery)query;
161
            ObjectBuildingQuery readQuery = (ObjectBuildingQuery)query;
165
            this.shouldBuildNullForNullPk = readQuery.shouldBuildNullForNullPk;
162
            this.shouldBuildNullForNullPk = readQuery.shouldBuildNullForNullPk;
166
            this.shouldProcessResultsInUnitOfWork = readQuery.shouldProcessResultsInUnitOfWork;
167
            this.shouldRefreshIdentityMapResult = readQuery.shouldRefreshIdentityMapResult;
163
            this.shouldRefreshIdentityMapResult = readQuery.shouldRefreshIdentityMapResult;
168
            this.shouldRefreshRemoteIdentityMapResult = readQuery.shouldRefreshRemoteIdentityMapResult;
164
            this.shouldRefreshRemoteIdentityMapResult = readQuery.shouldRefreshRemoteIdentityMapResult;
169
            this.shouldRegisterResultsInUnitOfWork = readQuery.shouldRegisterResultsInUnitOfWork;
165
            this.shouldRegisterResultsInUnitOfWork = readQuery.shouldRegisterResultsInUnitOfWork;
Lines 625-672 Link Here
625
    }
621
    }
626
622
627
    /**
623
    /**
628
     * ADVANCED:
629
     * Used for CMP only.  This allows users to indicate whether cmp finders executed
630
     * at the beginning of a transaction should always be run against a UnitOfWork.
631
     * Defaults to true.
632
     * <p>
633
     * If set to false, then UnitOfWork allocation will be deferred until a business
634
     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
635
     * is invoked.  Any finder executed before such a time, will do so against the
636
     * underlying ServerSession.  Forcing finder execution to always go through a
637
     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
638
     * front.  This is desired when the results will be accessed in the same transaction.
639
     * <p>
640
     * Note that finders executed with an unspecified transaction context will never
641
     * be executed against a UnitOfWork, even if this setting is true.  This case may happen
642
     * with the NotSupported, Never, and Supports attributes.
643
     */
644
    public void setShouldProcessResultsInUnitOfWork(boolean processResultsInUnitOfWork) {
645
        this.shouldProcessResultsInUnitOfWork = processResultsInUnitOfWork;
646
    }
647
648
    /**
649
     * ADVANCED:
650
     * Used for CMP only.  Indicates whether cmp finders executed at the beginning
651
     * of a transaction should always be run against a UnitOfWork.
652
     * Defaults to true.
653
     * <p>
654
     * If set to false, then UnitOfWork allocation will be deferred until a business
655
     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
656
     * is invoked.  Any finder executed before such a time, will do so against the
657
     * underlying ServerSession.  Forcing finder execution to always go through a
658
     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
659
     * front.  This is desired when the results will be accessed in the same transaction.
660
     * <p>
661
     * Note that finders executed with an unspecified transaction context will never
662
     * be executed against a UnitOfWork, even if this setting is true.  This case may happen
663
     * with the NotSupported, Never, and Supports attributes.
664
     */
665
    public boolean shouldProcessResultsInUnitOfWork() {
666
        return this.shouldProcessResultsInUnitOfWork;
667
    }
668
669
    /**
670
     * INTERNAL:
624
     * INTERNAL:
671
     * Return if the attribute is specified for joining.
625
     * Return if the attribute is specified for joining.
672
     */
626
     */
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelModifyQuery.java (-1 / +1 lines)
Lines 212-218 Link Here
212
212
213
        if (this.primaryKey == null) {
213
        if (this.primaryKey == null) {
214
            if (this.objectChangeSet != null) {
214
            if (this.objectChangeSet != null) {
215
                this.primaryKey = this.objectChangeSet.getPrimaryKeys();
215
                this.primaryKey = this.objectChangeSet.getId();
216
            } else {
216
            } else {
217
                this.primaryKey = this.descriptor.getObjectBuilder().extractPrimaryKeyFromObject(this.object, this.session);
217
                this.primaryKey = this.descriptor.getObjectBuilder().extractPrimaryKeyFromObject(this.object, this.session);
218
            }
218
            }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java (-121 lines)
Lines 1731-1746 Link Here
1731
1731
1732
    /**
1732
    /**
1733
     * INTERNAL:
1733
     * INTERNAL:
1734
     * Answers if we are executing through a UnitOfWork and registering results.
1735
     * This is only ever false if using the conforming without registering
1736
     * feature.
1737
     */
1738
    public boolean isRegisteringResults() {
1739
        return ((shouldRegisterResultsInUnitOfWork() && this.descriptor.shouldRegisterResultsInUnitOfWork()) || isLockQuery());
1740
    }
1741
1742
    /**
1743
     * INTERNAL:
1744
     * If changes are made to the query that affect the derived SQL or Call
1734
     * If changes are made to the query that affect the derived SQL or Call
1745
     * parameters the query needs to be prepared again.
1735
     * parameters the query needs to be prepared again.
1746
     * <p>
1736
     * <p>
Lines 2384-2421 Link Here
2384
2374
2385
    /**
2375
    /**
2386
     * PUBLIC:
2376
     * PUBLIC:
2387
     * Set if the attributes of the object(s) resulting from the query should be refreshed.
2388
     * If cascading is used the private parts of the objects will also be refreshed.
2389
     */
2390
    public void setShouldRefreshIdentityMapResult(boolean shouldRefreshIdentityMapResult) {
2391
        this.shouldRefreshIdentityMapResult = shouldRefreshIdentityMapResult;
2392
        if (shouldRefreshIdentityMapResult) {
2393
            setShouldRefreshRemoteIdentityMapResult(true);
2394
        }
2395
    }
2396
2397
    /**
2398
     * PUBLIC:
2399
     * Set if the attributes of the object(s) resulting from the query should be refreshed.
2400
     * If cascading is used the private parts of the objects will also be refreshed.
2401
     */
2402
    public void setShouldRefreshRemoteIdentityMapResult(boolean shouldRefreshIdentityMapResult) {
2403
        this.shouldRefreshRemoteIdentityMapResult = shouldRefreshIdentityMapResult;
2404
    }
2405
2406
    /**
2407
     * INTERNAL:
2408
     * Set to false to have queries conform to a UnitOfWork without registering
2409
     * any additional objects not already in that UnitOfWork.
2410
     * @see #shouldRegisterResultsInUnitOfWork
2411
     * @bug 2612601
2412
     */
2413
    public void setShouldRegisterResultsInUnitOfWork(boolean shouldRegisterResultsInUnitOfWork) {
2414
        this.shouldRegisterResultsInUnitOfWork = shouldRegisterResultsInUnitOfWork;
2415
    }
2416
2417
    /**
2418
     * PUBLIC:
2419
     * Return if cache should be checked.
2377
     * Return if cache should be checked.
2420
     */
2378
     */
2421
    public boolean shouldCheckCacheOnly() {
2379
    public boolean shouldCheckCacheOnly() {
Lines 2479-2503 Link Here
2479
        this.shouldOuterJoinSubclasses = Boolean.valueOf(shouldOuterJoinSubclasses);
2437
        this.shouldOuterJoinSubclasses = Boolean.valueOf(shouldOuterJoinSubclasses);
2480
        setIsPrepared(false);
2438
        setIsPrepared(false);
2481
    }
2439
    }
2482
    
2483
    /**
2484
     * INTERNAL:
2485
     * Allows one to do conforming in a UnitOfWork without registering.
2486
     * Queries executed on a UnitOfWork will only return working copies for objects
2487
     * that have already been registered.
2488
     * <p>Extreme care should be taken in using this feature, for a user will
2489
     * get back a mix of registered and original (unregistered) objects.
2490
     * <p>Best used with a WrapperPolicy where invoking on an object will trigger
2491
     * its registration (CMP).  Without a WrapperPolicy {@link org.eclipse.persistence.sessions.UnitOfWork#registerExistingObject registerExistingObject}
2492
     * should be called on any object that you intend to change.
2493
     * @return true by default.
2494
     * @see #setShouldRegisterResultsInUnitOfWork(boolean)
2495
     * @see org.eclipse.persistence.descriptors.ClassDescriptor#shouldRegisterResultsInUnitOfWork()
2496
     * @bug 2612601
2497
     */
2498
    public boolean shouldRegisterResultsInUnitOfWork() {
2499
        return shouldRegisterResultsInUnitOfWork;
2500
    }
2501
2440
2502
    /**
2441
    /**
2503
     * INTERNAL:
2442
     * INTERNAL:
Lines 2527-2593 Link Here
2527
    }
2466
    }
2528
2467
2529
    /**
2468
    /**
2530
     * PUBLIC:
2531
     * Set to a boolean. When set means refresh the instance
2532
     * variables of referenceObject from the database.
2533
     */
2534
    public boolean shouldRefreshIdentityMapResult() {
2535
        return shouldRefreshIdentityMapResult;
2536
    }
2537
2538
    /**
2539
     * PUBLIC:
2540
     * Set to a boolean. When set means refresh the instance
2541
     * variables of referenceObject from the database.
2542
     */
2543
    public boolean shouldRefreshRemoteIdentityMapResult() {
2544
        return shouldRefreshRemoteIdentityMapResult;
2545
    }
2546
2547
    /**
2548
     * ADVANCED:
2469
     * ADVANCED:
2549
     * Used for CMP only.  This allows users to indicate whether cmp finders executed
2550
     * at the beginning of a transaction should always be run against a UnitOfWork.
2551
     * Defaults to true.
2552
     * <p>
2553
     * If set to false, then UnitOfWork allocation will be deferred until a business
2554
     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
2555
     * is invoked.  Any finder executed before such a time, will do so against the
2556
     * underlying ServerSession.  Forcing finder execution to always go through a
2557
     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
2558
     * front.  This is desired when the results will be accessed in the same transaction.
2559
     * <p>
2560
     * Note that finders executed with an unspecified transaction context will never
2561
     * be executed against a UnitOfWork, even if this setting is true.  This case may happen
2562
     * with the NotSupported, Never, and Supports attributes.
2563
     */
2564
    public void setShouldProcessResultsInUnitOfWork(boolean processResultsInUnitOfWork) {
2565
        this.shouldProcessResultsInUnitOfWork = processResultsInUnitOfWork;
2566
    }
2567
2568
    /**
2569
     * ADVANCED:
2570
     * Used for CMP only.  Indicates whether cmp finders executed at the beginning
2571
     * of a transaction should always be run against a UnitOfWork.
2572
     * Defaults to true.
2573
     * <p>
2574
     * If set to false, then UnitOfWork allocation will be deferred until a business
2575
     * method (including creates/removes) or finder with shouldProcessResultsInUnitOfWork == true
2576
     * is invoked.  Any finder executed before such a time, will do so against the
2577
     * underlying ServerSession.  Forcing finder execution to always go through a
2578
     * UnitOfWork means the results will be cloned and cached in the UnitOfWork up
2579
     * front.  This is desired when the results will be accessed in the same transaction.
2580
     * <p>
2581
     * Note that finders executed with an unspecified transaction context will never
2582
     * be executed against a UnitOfWork, even if this setting is true.  This case may happen
2583
     * with the NotSupported, Never, and Supports attributes.
2584
     */
2585
    public boolean shouldProcessResultsInUnitOfWork() {
2586
        return this.shouldProcessResultsInUnitOfWork;
2587
    }
2588
2589
    /**
2590
     * ADVANCED:
2591
     * If a distinct has been set the DISTINCT clause will be printed.
2470
     * If a distinct has been set the DISTINCT clause will be printed.
2592
     * This is used internally by EclipseLink for batch reading but may also be
2471
     * This is used internally by EclipseLink for batch reading but may also be
2593
     * used directly for advanced queries or report queries.
2472
     * used directly for advanced queries or report queries.
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadObjectQuery.java (-34 / +38 lines)
Lines 15-20 Link Here
15
import java.util.*;
15
import java.util.*;
16
import java.sql.*;
16
import java.sql.*;
17
import org.eclipse.persistence.internal.databaseaccess.*;
17
import org.eclipse.persistence.internal.databaseaccess.*;
18
import org.eclipse.persistence.internal.identitymaps.CacheId;
18
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
19
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
19
import org.eclipse.persistence.internal.descriptors.*;
20
import org.eclipse.persistence.internal.descriptors.*;
20
import org.eclipse.persistence.internal.queries.CallQueryMechanism;
21
import org.eclipse.persistence.internal.queries.CallQueryMechanism;
Lines 46-52 Link Here
46
    protected transient Object selectionObject;
47
    protected transient Object selectionObject;
47
48
48
    /** Key that can be used in place of a selection criteria. */
49
    /** Key that can be used in place of a selection criteria. */
49
    protected Vector selectionKey;
50
    protected Object selectionId;
50
51
51
    /** Can be used to refresh a specific non-cached instance from the database. */
52
    /** Can be used to refresh a specific non-cached instance from the database. */
52
    protected boolean shouldLoadResultIntoSelectionObject = false;    
53
    protected boolean shouldLoadResultIntoSelectionObject = false;    
Lines 293-299 Link Here
293
                        // PERF: the read-object query should always be static to ensure no regeneration of SQL.
294
                        // PERF: the read-object query should always be static to ensure no regeneration of SQL.
294
                        if ((!hasJoining() || !getJoinedAttributeManager().hasJoinedAttributeExpressions()) && (!hasPartialAttributeExpressions()) && (!hasAsOfClause()) && (!hasNonDefaultFetchGroup()) && (getHintString() == null)
295
                        if ((!hasJoining() || !getJoinedAttributeManager().hasJoinedAttributeExpressions()) && (!hasPartialAttributeExpressions()) && (!hasAsOfClause()) && (!hasNonDefaultFetchGroup()) && (getHintString() == null)
295
                                && wasDefaultLockMode() && shouldIgnoreBindAllParameters() && (!hasFetchGroup()) && (getFetchGroupName() == null) && shouldUseDefaultFetchGroup()) {
296
                                && wasDefaultLockMode() && shouldIgnoreBindAllParameters() && (!hasFetchGroup()) && (getFetchGroupName() == null) && shouldUseDefaultFetchGroup()) {
296
                            if ((getSelectionKey() != null) || (getSelectionObject() != null)) {// Must be primary key.
297
                            if ((this.selectionId != null) || (this.selectionObject != null)) {// Must be primary key.
297
                                setIsCustomQueryUsed(true);
298
                                setIsCustomQueryUsed(true);
298
                            } else {            
299
                            } else {            
299
                                if (getSelectionCriteria() != null) {
300
                                if (getSelectionCriteria() != null) {
Lines 339-352 Link Here
339
                    this.descriptor.getObjectBuilder().unwrapObject(result, unitOfWork.getParent()),
340
                    this.descriptor.getObjectBuilder().unwrapObject(result, unitOfWork.getParent()),
340
                    null, unitOfWork, null, null);
341
                    null, unitOfWork, null, null);
341
        }
342
        }
342
343
        Expression selectionCriteria = getSelectionCriteria();
343
        if ((getSelectionCriteria() != null) && (getSelectionKey() == null) && (getSelectionObject() == null)) {
344
        if ((selectionCriteria != null) && (this.selectionId == null) && (this.selectionObject == null)) {
344
            ExpressionBuilder builder = getSelectionCriteria().getBuilder();
345
            ExpressionBuilder builder = selectionCriteria.getBuilder();
345
            builder.setSession(unitOfWork.getRootSession(null));
346
            builder.setSession(unitOfWork.getRootSession(null));
346
            builder.setQueryClass(getReferenceClass());
347
            builder.setQueryClass(getReferenceClass());
347
        }
348
        }
348
349
349
        clone = conformIndividualResult(clone, unitOfWork, databaseRow, getSelectionCriteria(), null);
350
        clone = conformIndividualResult(clone, unitOfWork, databaseRow, selectionCriteria, null);
350
        if (clone == null) {
351
        if (clone == null) {
351
            return clone;
352
            return clone;
352
        }
353
        }
Lines 446-453 Link Here
446
        }
447
        }
447
        if ((result == null) && shouldRefreshIdentityMapResult()) {
448
        if ((result == null) && shouldRefreshIdentityMapResult()) {
448
            // bug5955326, should invalidate the shared cached if refreshed object no longer exists.
449
            // bug5955326, should invalidate the shared cached if refreshed object no longer exists.
449
            if (getSelectionKey() != null) {
450
            if (getSelectionId() != null) {
450
                session.getParentIdentityMapSession(this, true, true).getIdentityMapAccessor().invalidateObject(getSelectionKey(), getReferenceClass());
451
                session.getParentIdentityMapSession(this, true, true).getIdentityMapAccessor().invalidateObject(getSelectionId(), getReferenceClass());
451
            } else if (getSelectionObject() != null) {
452
            } else if (getSelectionObject() != null) {
452
                session.getParentIdentityMapSession(this, true, true).getIdentityMapAccessor().invalidateObject(getSelectionObject());
453
                session.getParentIdentityMapSession(this, true, true).getIdentityMapAccessor().invalidateObject(getSelectionObject());
453
            }
454
            }
Lines 544-550 Link Here
544
     */
545
     */
545
    @Deprecated
546
    @Deprecated
546
    public Vector getSelectionKey() {
547
    public Vector getSelectionKey() {
547
        return selectionKey;
548
        if (this.selectionId instanceof CacheId) {
549
            return new Vector(Arrays.asList(((CacheId)this.selectionId).getPrimaryKey()));
550
        }
551
        Vector primaryKey = new Vector(1);
552
        primaryKey.add(this.selectionId);
553
        return (Vector)selectionId;
548
554
549
    }
555
    }
550
556
Lines 574-580 Link Here
574
     * Return if the query is by primary key.
580
     * Return if the query is by primary key.
575
     */
581
     */
576
    public boolean isPrimaryKeyQuery() {
582
    public boolean isPrimaryKeyQuery() {
577
        return (this.selectionKey != null) || (this.selectionObject != null);
583
        return (this.selectionId != null) || (this.selectionObject != null);
578
    }
584
    }
579
585
580
    /**
586
    /**
Lines 600-606 Link Here
600
        super.copyFromQuery(query);
606
        super.copyFromQuery(query);
601
        if (query.isReadObjectQuery()) {
607
        if (query.isReadObjectQuery()) {
602
            ReadObjectQuery readQuery = (ReadObjectQuery)query;
608
            ReadObjectQuery readQuery = (ReadObjectQuery)query;
603
            this.selectionKey = readQuery.selectionKey;
609
            this.selectionId = readQuery.selectionId;
604
            this.selectionObject = readQuery.selectionObject;
610
            this.selectionObject = readQuery.selectionObject;
605
            this.shouldLoadResultIntoSelectionObject = readQuery.shouldLoadResultIntoSelectionObject;
611
            this.shouldLoadResultIntoSelectionObject = readQuery.shouldLoadResultIntoSelectionObject;
606
        }
612
        }
Lines 616-638 Link Here
616
        }
622
        }
617
        super.prepare();
623
        super.prepare();
618
        
624
        
619
        if ((getSelectionKey() != null) || (getSelectionObject() != null)) {
625
        if ((this.selectionId != null) || (this.selectionObject != null)) {
620
            // The expression is set in the prepare as params.
626
            // The expression is set in the prepare as params.
621
            setSelectionCriteria(getDescriptor().getObjectBuilder().getPrimaryKeyExpression());
627
            setSelectionCriteria(this.descriptor.getObjectBuilder().getPrimaryKeyExpression());
622
            setExpressionBuilder(getSelectionCriteria().getBuilder());
628
            setExpressionBuilder(getSelectionCriteria().getBuilder());
623
            extendPessimisticLockScope();
629
            extendPessimisticLockScope();
624
            // For bug 2989998 the translation row is required to be set at this point.
630
            // For bug 2989998 the translation row is required to be set at this point.
625
            if (!shouldPrepare()) {
631
            if (!shouldPrepare()) {
626
                if (getSelectionKey() != null) {
632
                if (this.selectionId != null) {
627
                    // Row must come from the key.
633
                    // Row must come from the key.
628
                    setTranslationRow(getDescriptor().getObjectBuilder().buildRowFromPrimaryKeyValues(getSelectionKey(), getSession()));
634
                    setTranslationRow(getDescriptor().getObjectBuilder().buildRowFromPrimaryKeyValues(this.selectionId, getSession()));
629
                } else {//(getSelectionObject() != null)
635
                } else {//(getSelectionObject() != null)
630
                    setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(getSelectionObject(), getSession()));
636
                    setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(this.selectionObject, getSession()));
631
                }
637
                }
632
            }
638
            }
633
        }
639
        }
634
640
635
        if (getDescriptor().isDescriptorForInterface()) {
641
        if (this.descriptor.isDescriptorForInterface()) {
636
            return;
642
            return;
637
        }
643
        }
638
        
644
        
Lines 665-672 Link Here
665
            // CR#... Must also set the selection object as may be loading into the object (refresh)
671
            // CR#... Must also set the selection object as may be loading into the object (refresh)
666
            customReadQuery.selectionObject = this.selectionObject;
672
            customReadQuery.selectionObject = this.selectionObject;
667
            // The translation/primary key row will be set in prepareForExecution.
673
            // The translation/primary key row will be set in prepareForExecution.
668
        } else if (this.selectionKey != null) {
674
        } else if (this.selectionId != null) {
669
            customReadQuery.selectionKey = this.selectionKey;
675
            customReadQuery.selectionId = this.selectionId;
670
        } else {
676
        } else {
671
            // The primary key row must be used.
677
            // The primary key row must be used.
672
            primaryKeyRow = customQuery.getDescriptor().getObjectBuilder().extractPrimaryKeyRowFromExpression(getSelectionCriteria(), customQuery.getTranslationRow(), customReadQuery.getSession());
678
            primaryKeyRow = customQuery.getDescriptor().getObjectBuilder().extractPrimaryKeyRowFromExpression(getSelectionCriteria(), customQuery.getTranslationRow(), customReadQuery.getSession());
Lines 683-694 Link Here
683
689
684
        // For bug 2989998 the translation row now sometimes set earlier in prepare.
690
        // For bug 2989998 the translation row now sometimes set earlier in prepare.
685
        if (shouldPrepare()) {
691
        if (shouldPrepare()) {
686
            if (getSelectionKey() != null) {
692
            if (this.selectionId != null) {
687
                // Row must come from the key.
693
                // Row must come from the key.
688
                setTranslationRow(this.descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(getSelectionKey(), getSession()));
694
                this.translationRow = this.descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(this.selectionId, getSession());
689
            } else if (getSelectionObject() != null) {
695
            } else if (this.selectionObject != null) {
690
                // The expression is set in the prepare as params.
696
                // The expression is set in the prepare as params.
691
                setTranslationRow(this.descriptor.getObjectBuilder().buildRowForTranslation(getSelectionObject(), getSession()));
697
                this.translationRow = this.descriptor.getObjectBuilder().buildRowForTranslation(this.selectionObject, getSession());
692
            }
698
            }
693
        }
699
        }
694
    }
700
    }
Lines 773-779 Link Here
773
     * Return Id of the object to be selected by the query.
779
     * Return Id of the object to be selected by the query.
774
     */
780
     */
775
    public Object getSelectionId() {
781
    public Object getSelectionId() {
776
        return getSelectionKey();
782
        return this.selectionId;
777
    }
783
    }
778
784
779
    /**
785
    /**
Lines 782-812 Link Here
782
     * This will generate a query by primary key.
788
     * This will generate a query by primary key.
783
     * This can be used instead of an Expression, SQL, or JPQL, or example object.
789
     * This can be used instead of an Expression, SQL, or JPQL, or example object.
784
     * The Id is the Id value for a singleton primary key,
790
     * The Id is the Id value for a singleton primary key,
785
     * for a composite it is an instance of CacheKey.
791
     * for a composite it is an instance of CacheId.
786
     * @see CacheKey
792
     * @see CacheId
787
     */
793
     */
788
    public void setSelectionId(Object id) {
794
    public void setSelectionId(Object id) {
789
        setSelectionKey((Vector)id);
795
        this.selectionId = id;
790
    }
796
    }
791
797
792
    /**
798
    /**
793
     * PUBLIC:
799
     * PUBLIC:
794
     * The primary key can be specified if used instead of an expression or selection object.
800
     * The primary key can be specified if used instead of an expression or selection object.
795
     * If composite the primary must be in the same order as defined in the descriptor.
801
     * If composite the primary must be in the same order as defined in the descriptor.
796
     * @Depreacted since EclipseLink 2.1, replaced by setSelectionId(Object)
802
     * @depreacted since EclipseLink 2.1, replaced by setSelectionId(Object)
797
     * @see #setSelectionId(Object)
803
     * @see #setSelectionId(Object)
798
     */
804
     */
799
    @Deprecated
805
    @Deprecated
800
    public void setSelectionKey(List selectionKey) {
806
    public void setSelectionKey(List selectionKey) {
801
        if (selectionKey == null) {
807
        if (selectionKey == null) {
802
            this.selectionKey = null;
808
            this.selectionId = null;
803
        } else if (selectionKey instanceof NonSynchronizedVector) {
809
        } else if (selectionKey.size() == 1) {
804
            this.selectionKey = (Vector)selectionKey;
810
            this.selectionId = selectionKey.get(0);            
805
        } else {
811
        } else {
806
            this.selectionKey = new NonSynchronizedVector(selectionKey);            
812
            this.selectionId = new CacheId(selectionKey.toArray());
807
        }
813
        }
808
        // setIsPrepared(false); PERF: This cause the findByPrimaryKey query to unprepare,
809
        // Since this is an argument, and not a query modifier do not unprepare.
810
    }
814
    }
811
815
812
    /**
816
    /**
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReportQueryResult.java (-10 / +13 lines)
Lines 22-27 Link Here
22
import org.eclipse.persistence.exceptions.*;
22
import org.eclipse.persistence.exceptions.*;
23
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
23
import org.eclipse.persistence.internal.expressions.MapEntryExpression;
24
import org.eclipse.persistence.internal.helper.*;
24
import org.eclipse.persistence.internal.helper.*;
25
import org.eclipse.persistence.internal.identitymaps.CacheId;
25
import org.eclipse.persistence.internal.queries.*;
26
import org.eclipse.persistence.internal.queries.*;
26
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
27
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
27
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
28
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
Lines 221-230 Link Here
221
                if (this.key != null) {
222
                if (this.key != null) {
222
                    Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(subRow, query.getSession());
223
                    Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromRow(subRow, query.getSession());
223
                    if (primaryKey != null){//GF3233 NPE is caused by processing the null PK being extracted from referenced target with null values in database.
224
                    if (primaryKey != null){//GF3233 NPE is caused by processing the null PK being extracted from referenced target with null values in database.
224
                        for (Iterator iterator = ((Vector)primaryKey).iterator(); iterator.hasNext();){
225
                        this.key.append(primaryKey);
225
                           this.key.append(iterator.next());
226
                           this.key.append("-");
227
                        }
228
                    }
226
                    }
229
                    this.key.append("_");
227
                    this.key.append("_");
230
                }
228
                }
Lines 433-443 Link Here
433
        }
431
        }
434
432
435
        // Compare PKs
433
        // Compare PKs
436
        if (getPrimaryKeyValues() != null) {
434
        if (getId() != null) {
437
            if (result.getPrimaryKeyValues() == null) {
435
            if (result.getId() == null) {
438
                return false;
436
                return false;
439
            }
437
            }
440
            return Helper.compareOrderedVectors(getPrimaryKeyValues(), result.getPrimaryKeyValues());
438
            return getId().equals(getId());
441
        }
439
        }
442
440
443
        return true;
441
        return true;
Lines 511-517 Link Here
511
     */
509
     */
512
    @Deprecated
510
    @Deprecated
513
    public Vector<Object> getPrimaryKeyValues() {
511
    public Vector<Object> getPrimaryKeyValues() {
514
        return (Vector)primaryKey;
512
        if (this.primaryKey instanceof CacheId) {
513
            return new Vector(Arrays.asList(((CacheId)this.primaryKey).getPrimaryKey()));
514
        }
515
        Vector primaryKey = new Vector(1);
516
        primaryKey.add(this.primaryKey);
517
        return primaryKey;
515
    }
518
    }
516
519
517
    /**
520
    /**
Lines 596-607 Link Here
596
     * If the PKs were retrieved with the attributes then this method can be used to read the real object from the database.
599
     * If the PKs were retrieved with the attributes then this method can be used to read the real object from the database.
597
     */
600
     */
598
    public Object readObject(Class javaClass, Session session) {
601
    public Object readObject(Class javaClass, Session session) {
599
        if (getPrimaryKeyValues() == null) {
602
        if (getId() == null) {
600
            throw QueryException.reportQueryResultWithoutPKs(this);
603
            throw QueryException.reportQueryResultWithoutPKs(this);
601
        }
604
        }
602
605
603
        ReadObjectQuery query = new ReadObjectQuery(javaClass);
606
        ReadObjectQuery query = new ReadObjectQuery(javaClass);
604
        query.setSelectionId(getPrimaryKeyValues());
607
        query.setSelectionId(getId());
605
608
606
        return session.executeQuery(query);
609
        return session.executeQuery(query);
607
    }
610
    }
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/changesets/ObjectChangeSet.java (-2 / +11 lines)
Lines 25-31 Link Here
25
 * <p>
25
 * <p>
26
 */
26
 */
27
public interface ObjectChangeSet {
27
public interface ObjectChangeSet {
28
    boolean equals(ObjectChangeSet objectChange);
28
    boolean equals(Object objectChange);
29
29
30
    /**
30
    /**
31
     * ADVANCED:
31
     * ADVANCED:
Lines 67-78 Link Here
67
67
68
    /**
68
    /**
69
     * ADVANCED:
69
     * ADVANCED:
70
     * This method returns the primary keys for the object that this change set represents.
70
     * This method returns the primary key for the object that this change set represents.
71
     * @depreated since EclipseLink 2.1, replaced by getPrimaryKey()
72
     * @see getPrimaryKey()
71
     */
73
     */
74
    @Deprecated
72
    Vector getPrimaryKeys();
75
    Vector getPrimaryKeys();
73
76
74
    /**
77
    /**
75
     * ADVANCED:
78
     * ADVANCED:
79
     * This method returns the primary key for the object that this change set represents.
80
     */
81
    Object getId();
82
83
    /**
84
     * ADVANCED:
76
     * This method is used to return the parent ChangeSet.
85
     * This method is used to return the parent ChangeSet.
77
     */
86
     */
78
    UnitOfWorkChangeSet getUOWChangeSet();
87
    UnitOfWorkChangeSet getUOWChangeSet();
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/interceptors/CacheKeyInterceptor.java (-1 / +1 lines)
Lines 122-128 Link Here
122
            return wrappedKey.getLastUpdatedQueryId();
122
            return wrappedKey.getLastUpdatedQueryId();
123
        }
123
        }
124
124
125
        public Vector getKey() {
125
        public Object getKey() {
126
            return wrappedKey.getKey();
126
            return wrappedKey.getKey();
127
        }
127
        }
128
128
(-)foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/tools/schemaframework/PopulationManager.java (-6 / +4 lines)
Lines 46-54 Link Here
46
    public void addAllObjectsForAbstractClass(Class objectsClass, AbstractSession session, Vector allObjects) {
46
    public void addAllObjectsForAbstractClass(Class objectsClass, AbstractSession session, Vector allObjects) {
47
        ClassDescriptor descriptor = session.getDescriptor(objectsClass);
47
        ClassDescriptor descriptor = session.getDescriptor(objectsClass);
48
        addAllObjectsForClass(objectsClass, allObjects);
48
        addAllObjectsForClass(objectsClass, allObjects);
49
        for (Enumeration enumeration = descriptor.getInheritancePolicy().getChildDescriptors().elements();
49
        for (ClassDescriptor child : descriptor.getInheritancePolicy().getChildDescriptors()) {
50
                 enumeration.hasMoreElements();) {
50
            addAllObjectsForAbstractClass(child.getJavaClass(), session, allObjects);
51
            addAllObjectsForAbstractClass(((ClassDescriptor)enumeration.nextElement()).getJavaClass(), session, allObjects);
52
        }
51
        }
53
    }
52
    }
54
53
Lines 136-144 Link Here
136
        Vector allObjects = new Vector();
135
        Vector allObjects = new Vector();
137
        addAllObjectsForClass(objectsClass, allObjects);
136
        addAllObjectsForClass(objectsClass, allObjects);
138
        if (descriptor.hasInheritance()) {
137
        if (descriptor.hasInheritance()) {
139
            for (Enumeration enumeration = descriptor.getInheritancePolicy().getChildDescriptors().elements();
138
            for (ClassDescriptor child : descriptor.getInheritancePolicy().getChildDescriptors()) {
140
                     enumeration.hasMoreElements();) {
139
                addAllObjectsForClass(child.getJavaClass(), allObjects);
141
                addAllObjectsForClass(((ClassDescriptor)enumeration.nextElement()).getJavaClass(), allObjects);
142
            }
140
            }
143
        }
141
        }
144
142
(-)jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/AdvancedJunitTest.java (-5 / +1 lines)
Lines 231-246 Link Here
231
            PartnerLinkPK usedPk = new PartnerLinkPK(pLink3.getManId(), pLink3.getWomanId());
231
            PartnerLinkPK usedPk = new PartnerLinkPK(pLink3.getManId(), pLink3.getWomanId());
232
            assertTrue("PK's do not match.", usedPk.equals(createdPK));
232
            assertTrue("PK's do not match.", usedPk.equals(createdPK));
233
233
234
        } catch (RuntimeException e) {
234
        } finally {
235
            if (isTransactionActive(em)) {
235
            if (isTransactionActive(em)) {
236
                rollbackTransaction(em);
236
                rollbackTransaction(em);
237
            }
237
            }
238
239
            closeEntityManager(em);
238
            closeEntityManager(em);
240
            fail("An exception was caught: [" + e.getMessage() + "]");
241
        }
239
        }
242
243
        closeEntityManager(em);
244
    }
240
    }
245
241
246
    // GF1673, 2674 Java SE 6 classloading error for String[] field
242
    // GF1673, 2674 Java SE 6 classloading error for String[] field
(-)jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/sessionbean/SessionBeanTestsRCM.java (-1 / +1 lines)
Lines 169-175 Link Here
169
        empId = getEmployeeService(server1Url).insert(employee);	
169
        empId = getEmployeeService(server1Url).insert(employee);	
170
	
170
	
171
	/* read Employee from cache and/or DB */
171
	/* read Employee from cache and/or DB */
172
	Employee jane1 = (Employee) getEmployeeService(server1Url).findById(empId);
172
	Employee jane1 = getEmployeeService(server1Url).findById(empId);
173
	/* update employee on Server1 */
173
	/* update employee on Server1 */
174
        jane1.setLastName("LastNameUpdatedOnServer1");
174
        jane1.setLastName("LastNameUpdatedOnServer1");
175
        jane1.getAddress().setCity("newCity");
175
        jane1.getAddress().setCity("newCity");
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/CacheImpl.java (-6 / +5 lines)
Lines 12-18 Link Here
12
 ******************************************************************************/
12
 ******************************************************************************/
13
package org.eclipse.persistence.internal.jpa;
13
package org.eclipse.persistence.internal.jpa;
14
14
15
import java.util.Vector;
16
import javax.persistence.Cache;
15
import javax.persistence.Cache;
17
import org.eclipse.persistence.descriptors.ClassDescriptor;
16
import org.eclipse.persistence.descriptors.ClassDescriptor;
18
import org.eclipse.persistence.internal.identitymaps.CacheKey;
17
import org.eclipse.persistence.internal.identitymaps.CacheKey;
Lines 37-52 Link Here
37
36
38
    public boolean contains(Class cls, Object primaryKey) {
37
    public boolean contains(Class cls, Object primaryKey) {
39
        this.emf.verifyOpen();
38
        this.emf.verifyOpen();
40
        Vector pk =  createPKVector(cls, primaryKey);
39
        Object pk =  createPrimaryKeyFromId(cls, primaryKey);
41
        ClassDescriptor descriptor = this.serversession.getDescriptor(cls);
40
        ClassDescriptor descriptor = this.serversession.getDescriptor(cls);
42
        CacheKey key = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor)this.accessor).getCacheKeyForObject(pk, cls, descriptor);
41
        CacheKey key = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor)this.accessor).getCacheKeyForObject(pk, cls, descriptor);
43
42
44
        return key != null && !descriptor.getCacheInvalidationPolicy().isInvalidated(key); 
43
        return (key != null) && (key.getObject() != null) && (!descriptor.getCacheInvalidationPolicy().isInvalidated(key)); 
45
    }
44
    }
46
45
47
    public void evict(Class cls, Object primaryKey) {
46
    public void evict(Class cls, Object primaryKey) {
48
        this.emf.verifyOpen();
47
        this.emf.verifyOpen();
49
        this.accessor.invalidateObject(createPKVector(cls, primaryKey), cls);
48
        this.accessor.invalidateObject(createPrimaryKeyFromId(cls, primaryKey), cls);
50
    }
49
    }
51
50
52
    public void evict(Class cls) {
51
    public void evict(Class cls) {
Lines 59-68 Link Here
59
        this.accessor.invalidateAll();
58
        this.accessor.invalidateAll();
60
    }
59
    }
61
60
62
    private Vector createPKVector(Class cls, Object primaryKey){
61
    private Object createPrimaryKeyFromId(Class cls, Object primaryKey){
63
        ClassDescriptor cdesc = this.serversession.getDescriptor(cls);
62
        ClassDescriptor cdesc = this.serversession.getDescriptor(cls);
64
        CMP3Policy cmp = (CMP3Policy) (cdesc.getCMPPolicy());
63
        CMP3Policy cmp = (CMP3Policy) (cdesc.getCMPPolicy());
65
        Vector pk = cmp.createPkVectorFromKey(primaryKey, this.serversession);
64
        Object pk = cmp.createPrimaryKeyFromId(primaryKey, this.serversession);
66
        return pk;
65
        return pk;
67
    }
66
    }
68
}
67
}
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/CMP3Policy.java (-9 / +15 lines)
Lines 23-37 Link Here
23
import java.security.AccessController;
23
import java.security.AccessController;
24
import java.security.PrivilegedActionException;
24
import java.security.PrivilegedActionException;
25
import java.util.*;
25
import java.util.*;
26
27
import org.eclipse.persistence.annotations.CacheKeyType;
26
import org.eclipse.persistence.descriptors.*;
28
import org.eclipse.persistence.descriptors.*;
27
import org.eclipse.persistence.internal.helper.ConversionManager;
29
import org.eclipse.persistence.internal.helper.ConversionManager;
28
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
29
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
30
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
30
import org.eclipse.persistence.internal.sessions.AbstractSession;
31
import org.eclipse.persistence.internal.sessions.AbstractSession;
31
import org.eclipse.persistence.mappings.DatabaseMapping;
32
import org.eclipse.persistence.mappings.DatabaseMapping;
32
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
33
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
33
import org.eclipse.persistence.exceptions.*;
34
import org.eclipse.persistence.exceptions.*;
34
import org.eclipse.persistence.internal.helper.DatabaseField;
35
import org.eclipse.persistence.internal.helper.DatabaseField;
36
import org.eclipse.persistence.internal.identitymaps.CacheId;
35
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
37
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
36
import org.eclipse.persistence.internal.security.PrivilegedGetField;
38
import org.eclipse.persistence.internal.security.PrivilegedGetField;
37
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
39
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
Lines 182-201 Link Here
182
    
184
    
183
    /**
185
    /**
184
     * INTERNAL:
186
     * INTERNAL:
185
     * Use the key to create a EclipseLink primary key Vector.
187
     * Use the key to create a EclipseLink primary key.
186
     * If the key is simple (direct mapped) then just add it to a vector,
188
     * If the key is simple (direct mapped) then just add it to a vector,
187
     * otherwise must go through the inefficient process of copying the key into the bean
189
     * otherwise must go through the inefficient process of copying the key into the bean
188
     * and extracting the key from the bean.
190
     * and extracting the key from the bean.
189
     *
190
     * @param key Object the primary key to use for creating the vector
191
     * @return Vector
192
     */
191
     */
193
    public Vector createPkVectorFromKey(Object key, AbstractSession session) {
192
    @Override
193
    public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
194
        // If the descriptor primary key is mapped through direct-to-field mappings,
194
        // If the descriptor primary key is mapped through direct-to-field mappings,
195
        // then no elaborate conversion is required.
195
        // then no elaborate conversion is required.
196
        // If key is compound, add each value to the vector.
196
        // If key is compound, add each value to the vector.
197
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(key.getClass());
197
        KeyElementAccessor[] pkElementArray = this.getKeyClassFields(key.getClass());
198
        Vector pkVector = new NonSynchronizedVector(pkElementArray.length);
198
        Object[] primaryKey = null;
199
        if (getDescriptor().getCacheKeyType() != CacheKeyType.ID_VALUE) {
200
            primaryKey = new Object[pkElementArray.length];
201
        }
199
        for (int index = 0; index < pkElementArray.length; index++) {
202
        for (int index = 0; index < pkElementArray.length; index++) {
200
            DatabaseMapping mapping = pkElementArray[index].getMapping();
203
            DatabaseMapping mapping = pkElementArray[index].getMapping();
201
            Object fieldValue = null;
204
            Object fieldValue = null;
Lines 216-224 Link Here
216
                    }
219
                    }
217
                }
220
                }
218
            }
221
            }
219
            pkVector.add(fieldValue);
222
            if (getDescriptor().getCacheKeyType() == CacheKeyType.ID_VALUE) {
223
                return fieldValue;
224
            }
225
            primaryKey[index] = fieldValue;
220
        }
226
        }
221
        return pkVector;
227
        return new CacheId(primaryKey);
222
    }
228
    }
223
    
229
    
224
    /**
230
    /**
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerImpl.java (-15 / +24 lines)
Lines 33-45 Link Here
33
import javax.persistence.metamodel.Metamodel;
33
import javax.persistence.metamodel.Metamodel;
34
import javax.sql.DataSource;
34
import javax.sql.DataSource;
35
35
36
import org.eclipse.persistence.annotations.CacheKeyType;
36
import org.eclipse.persistence.config.*;
37
import org.eclipse.persistence.config.*;
37
import org.eclipse.persistence.descriptors.*;
38
import org.eclipse.persistence.descriptors.*;
38
import org.eclipse.persistence.exceptions.*;
39
import org.eclipse.persistence.exceptions.*;
39
import org.eclipse.persistence.expressions.Expression;
40
import org.eclipse.persistence.expressions.Expression;
40
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
41
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
41
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
42
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
42
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
43
import org.eclipse.persistence.internal.identitymaps.CacheId;
43
import org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl;
44
import org.eclipse.persistence.internal.jpa.querydef.CriteriaQueryImpl;
44
import org.eclipse.persistence.internal.jpa.transaction.*;
45
import org.eclipse.persistence.internal.jpa.transaction.*;
45
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
46
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
Lines 633-655 Link Here
633
     *             second argument is not a valid type for that entity's primary
634
     *             second argument is not a valid type for that entity's primary
634
     *             key.
635
     *             key.
635
     */
636
     */
636
    protected Object findInternal(ClassDescriptor descriptor, AbstractSession session, Object primaryKey, LockModeType lockMode, Map<String, Object> properties) {
637
    protected Object findInternal(ClassDescriptor descriptor, AbstractSession session, Object id, LockModeType lockMode, Map<String, Object> properties) {
637
        if (primaryKey == null) { // gf721 - check for null PK
638
        if (id == null) { // gf721 - check for null PK
638
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
639
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
639
        }
640
        }
640
641
641
        List primaryKeyValues;
642
        Object primaryKey;
642
        if (primaryKey instanceof Vector) {
643
        if (id instanceof List) {
643
            primaryKeyValues = (Vector)primaryKey;
644
            if (descriptor.getCacheKeyType() == CacheKeyType.ID_VALUE) {
644
        } else if (primaryKey instanceof List) {
645
                if (((List)id).isEmpty()) {
645
            primaryKeyValues = new NonSynchronizedVector((List)primaryKey);
646
                    primaryKey = null;
647
                } else {
648
                    primaryKey = ((List)id).get(0);
649
                }
650
            } else {
651
                primaryKey = new CacheId(((List)id).toArray());
652
            }
653
        } else if (id instanceof CacheId) {
654
            primaryKey = id;
646
        } else {
655
        } else {
647
            CMPPolicy policy = descriptor.getCMPPolicy();
656
            CMPPolicy policy = descriptor.getCMPPolicy();
648
            Class pkClass = policy.getPKClass();
657
            Class pkClass = policy.getPKClass();
649
            if ((pkClass != null) && (! BasicTypeHelperImpl.getInstance().isStrictlyAssignableFrom(pkClass, primaryKey.getClass())) ) {
658
            if ((pkClass != null) && (pkClass != id.getClass()) && (!BasicTypeHelperImpl.getInstance().isStrictlyAssignableFrom(pkClass, id.getClass()))) {
650
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), primaryKey.getClass() }));
659
                throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), id.getClass() }));
651
            }
660
            }
652
            primaryKeyValues = policy.createPkVectorFromKey(primaryKey, session);
661
            primaryKey = policy.createPrimaryKeyFromId(id, session);
653
        }
662
        }
654
663
655
        // Get the read object query and apply the properties to it.
664
        // Get the read object query and apply the properties to it.
Lines 659-665 Link Here
659
        if (query == null) {
668
        if (query == null) {
660
            // The properties/query hints and setIsExecutionClone etc. is set
669
            // The properties/query hints and setIsExecutionClone etc. is set
661
            // in the getReadObjectQuery.
670
            // in the getReadObjectQuery.
662
            query = getReadObjectQuery(descriptor.getJavaClass(), primaryKeyValues, properties);
671
            query = getReadObjectQuery(descriptor.getJavaClass(), primaryKey, properties);
663
        } else {
672
        } else {
664
            query.checkPrepare(session, null);
673
            query.checkPrepare(session, null);
665
            query = (ReadObjectQuery) query.clone();
674
            query = (ReadObjectQuery) query.clone();
Lines 668-674 Link Here
668
            QueryHintsHandler.apply(properties, query, session.getLoader(), session);
677
            QueryHintsHandler.apply(properties, query, session.getLoader(), session);
669
678
670
            query.setIsExecutionClone(true);
679
            query.setIsExecutionClone(true);
671
            query.setSelectionId(primaryKeyValues);
680
            query.setSelectionId(primaryKey);
672
        }
681
        }
673
682
674
        // Apply any EclipseLink defaults if they haven't been set through
683
        // Apply any EclipseLink defaults if they haven't been set through
Lines 1135-1144 Link Here
1135
    /**
1144
    /**
1136
     * Build a selection query for the primary key values.
1145
     * Build a selection query for the primary key values.
1137
     */
1146
     */
1138
    protected ReadObjectQuery getReadObjectQuery(Class referenceClass, List primaryKeyValues, Map properties) {
1147
    protected ReadObjectQuery getReadObjectQuery(Class referenceClass, Object primaryKey, Map properties) {
1139
        ReadObjectQuery query = getReadObjectQuery(properties);
1148
        ReadObjectQuery query = getReadObjectQuery(properties);
1140
        query.setReferenceClass(referenceClass);
1149
        query.setReferenceClass(referenceClass);
1141
        query.setSelectionId(primaryKeyValues);
1150
        query.setSelectionId(primaryKey);
1142
        return query;
1151
        return query;
1143
    }
1152
    }
1144
1153
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/PrimaryKeyMetadata.java (+5 lines)
Lines 15-20 Link Here
15
import java.util.ArrayList;
15
import java.util.ArrayList;
16
import java.util.List;
16
import java.util.List;
17
17
18
import org.eclipse.persistence.annotations.CacheKeyType;
18
import org.eclipse.persistence.annotations.IdValidation;
19
import org.eclipse.persistence.annotations.IdValidation;
19
import org.eclipse.persistence.annotations.PrimaryKey;
20
import org.eclipse.persistence.annotations.PrimaryKey;
20
import org.eclipse.persistence.exceptions.ValidationException;
21
import org.eclipse.persistence.exceptions.ValidationException;
Lines 33-38 Link Here
33
 */
34
 */
34
public class PrimaryKeyMetadata extends ORMetadata {
35
public class PrimaryKeyMetadata extends ORMetadata {
35
    private String m_validation;
36
    private String m_validation;
37
    private String m_cacheKeyType;
36
    private List<ColumnMetadata> m_columns = new ArrayList<ColumnMetadata>();
38
    private List<ColumnMetadata> m_columns = new ArrayList<ColumnMetadata>();
37
39
38
    public PrimaryKeyMetadata() {
40
    public PrimaryKeyMetadata() {
Lines 60-65 Link Here
60
        if (m_validation != null) {
62
        if (m_validation != null) {
61
            descriptor.getClassDescriptor().setIdValidation(IdValidation.valueOf(m_validation));
63
            descriptor.getClassDescriptor().setIdValidation(IdValidation.valueOf(m_validation));
62
        }
64
        }
65
        if (m_cacheKeyType != null) {
66
            descriptor.getClassDescriptor().setCacheKeyType(CacheKeyType.valueOf(m_cacheKeyType));
67
        }
63
        if (hasColumns()) {
68
        if (hasColumns()) {
64
        	List fields = new ArrayList(m_columns.size());
69
        	List fields = new ArrayList(m_columns.size());
65
            for (ColumnMetadata column : m_columns) {
70
            for (ColumnMetadata column : m_columns) {
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/xml/XMLEntityMappingsMappingProject.java (+5 lines)
Lines 1794-1799 Link Here
1794
        validationMapping.setXPath("@validation");
1794
        validationMapping.setXPath("@validation");
1795
        descriptor.addMapping(validationMapping);
1795
        descriptor.addMapping(validationMapping);
1796
        
1796
        
1797
        XMLDirectMapping cacheKeyMapping = new XMLDirectMapping();
1798
        cacheKeyMapping.setAttributeName("m_cacheKeyType");
1799
        cacheKeyMapping.setXPath("@cache-key-type");
1800
        descriptor.addMapping(cacheKeyMapping);
1801
        
1797
        XMLCompositeCollectionMapping columnsMapping = new XMLCompositeCollectionMapping();
1802
        XMLCompositeCollectionMapping columnsMapping = new XMLCompositeCollectionMapping();
1798
        columnsMapping.setAttributeName("m_columns");
1803
        columnsMapping.setAttributeName("m_columns");
1799
        columnsMapping.setReferenceClass(ColumnMetadata.class);
1804
        columnsMapping.setReferenceClass(ColumnMetadata.class);
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/weaving/ClassWeaver.java (-38 / +13 lines)
Lines 54-59 Link Here
54
    public static final String PERSISTENCE_OBJECT_SHORT_SIGNATURE = "org/eclipse/persistence/internal/descriptors/PersistenceObject";
54
    public static final String PERSISTENCE_OBJECT_SHORT_SIGNATURE = "org/eclipse/persistence/internal/descriptors/PersistenceObject";
55
    public static final String PERSISTENCE_OBJECT_SIGNATURE = "L" + PERSISTENCE_OBJECT_SHORT_SIGNATURE + ";";
55
    public static final String PERSISTENCE_OBJECT_SIGNATURE = "L" + PERSISTENCE_OBJECT_SHORT_SIGNATURE + ";";
56
    public static final String VECTOR_SIGNATURE = "Ljava/util/Vector;";
56
    public static final String VECTOR_SIGNATURE = "Ljava/util/Vector;";
57
    public static final String OBJECT_SIGNATURE = "Ljava/lang/Object;";
57
    public static final String CACHEKEY_SIGNATURE = "Lorg/eclipse/persistence/internal/identitymaps/CacheKey;";
58
    public static final String CACHEKEY_SIGNATURE = "Lorg/eclipse/persistence/internal/identitymaps/CacheKey;";
58
    
59
    
59
    // Fetch groups
60
    // Fetch groups
Lines 608-622 Link Here
608
    }
609
    }
609
    
610
    
610
    /**
611
    /**
611
     * Add a variable of type Vector, CacheKey to the class.
612
     * Add a variable of type Object to the class.
612
     * When this method has been run, the class will contain a variable declarations similar to the following:
613
     * When this method has been run, the class will contain a variable declarations similar to the following:
613
     *  
614
     *  
614
     *  private Vector _persistence_primaryKey;
615
     *  private Object _persistence_primaryKey;
615
     *  private Vector _persistence_cacheKey;
616
     */
616
     */
617
    public void addPersistenceEntityVariables() {
617
    public void addPersistenceEntityVariables() {
618
        cv.visitField(ACC_PROTECTED + ACC_TRANSIENT, "_persistence_primaryKey", VECTOR_SIGNATURE, null, null);
618
        cv.visitField(ACC_PROTECTED + ACC_TRANSIENT, "_persistence_primaryKey", OBJECT_SIGNATURE, null, null);
619
        cv.visitField(ACC_PROTECTED + ACC_TRANSIENT, "_persistence_cacheKey", CACHEKEY_SIGNATURE, null, null);
620
    }
619
    }
621
    
620
    
622
    /**
621
    /**
Lines 681-691 Link Here
681
	        // clone._persistence_primaryKey = null;
680
	        // clone._persistence_primaryKey = null;
682
	        cv_clone.visitVarInsn(ALOAD, 0);
681
	        cv_clone.visitVarInsn(ALOAD, 0);
683
	        cv_clone.visitInsn(ACONST_NULL);
682
	        cv_clone.visitInsn(ACONST_NULL);
684
	        cv_clone.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_primaryKey", VECTOR_SIGNATURE);
683
	        cv_clone.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_primaryKey", OBJECT_SIGNATURE);
685
	        // clone._persistence_cacheKey = null;
686
	        cv_clone.visitVarInsn(ALOAD, 0);
687
	        cv_clone.visitInsn(ACONST_NULL);
688
	        cv_clone.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_cacheKey", CACHEKEY_SIGNATURE);
689
        }
684
        }
690
        
685
        
691
        // return clone;
686
        // return clone;
Lines 874-918 Link Here
874
    /**
869
    /**
875
     * Adds get/set method for PersistenceEntity interface.
870
     * Adds get/set method for PersistenceEntity interface.
876
     * This adds the following methods:
871
     * This adds the following methods:
877
     * 
878
     *  public CacheKey _persistence_getCacheKey() {
879
     *      return _persistence_cacheKey;
880
     *  }
881
     *  public void _persistence_setCacheKey(CacheKey key) {
882
     *      this._persistence_cacheKey = key;
883
     *  }
884
     *   
872
     *   
885
     *  public Vector _persistence_getPKVector() {
873
     *  public Object _persistence_getId() {
886
     *      return _persistence_primaryKey;
874
     *      return _persistence_primaryKey;
887
     *  }
875
     *  }
888
     *  public void _persistence_setPKVector(Vector pk) {
876
     *  public void _persistence_setId(Object primaryKey) {
889
     *      this._persistence_primaryKey = pk;
877
     *      this._persistence_primaryKey = primaryKey;
890
     *  }
878
     *  }
891
     */
879
     */
892
    public void addPersistenceEntityMethods(ClassDetails classDetails) {
880
    public void addPersistenceEntityMethods(ClassDetails classDetails) {        
893
        CodeVisitor cv_getCacheKey = cv.visitMethod(ACC_PUBLIC, "_persistence_getCacheKey", "()" + CACHEKEY_SIGNATURE, null, null);
881
        CodeVisitor cv_getPKVector = cv.visitMethod(ACC_PUBLIC, "_persistence_getId", "()" + OBJECT_SIGNATURE, null, null);
894
        cv_getCacheKey.visitVarInsn(ALOAD, 0);
895
        cv_getCacheKey.visitFieldInsn(GETFIELD, classDetails.getClassName(), "_persistence_cacheKey", CACHEKEY_SIGNATURE);
896
        cv_getCacheKey.visitInsn(ARETURN);
897
        cv_getCacheKey.visitMaxs(0, 0);
898
        
899
        CodeVisitor cv_setCacheKey = cv.visitMethod(ACC_PUBLIC, "_persistence_setCacheKey", "(" + CACHEKEY_SIGNATURE + ")V", null, null);
900
        cv_setCacheKey.visitVarInsn(ALOAD, 0);
901
        cv_setCacheKey.visitVarInsn(ALOAD, 1);
902
        cv_setCacheKey.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_cacheKey", CACHEKEY_SIGNATURE);
903
        cv_setCacheKey.visitInsn(RETURN);
904
        cv_setCacheKey.visitMaxs(0 ,0);
905
        
906
        CodeVisitor cv_getPKVector = cv.visitMethod(ACC_PUBLIC, "_persistence_getPKVector", "()" + VECTOR_SIGNATURE, null, null);
907
        cv_getPKVector.visitVarInsn(ALOAD, 0);
882
        cv_getPKVector.visitVarInsn(ALOAD, 0);
908
        cv_getPKVector.visitFieldInsn(GETFIELD, classDetails.getClassName(), "_persistence_primaryKey", VECTOR_SIGNATURE);
883
        cv_getPKVector.visitFieldInsn(GETFIELD, classDetails.getClassName(), "_persistence_primaryKey", OBJECT_SIGNATURE);
909
        cv_getPKVector.visitInsn(ARETURN);
884
        cv_getPKVector.visitInsn(ARETURN);
910
        cv_getPKVector.visitMaxs(0, 0);
885
        cv_getPKVector.visitMaxs(0, 0);
911
        
886
        
912
        CodeVisitor cv_setPKVector = cv.visitMethod(ACC_PUBLIC, "_persistence_setPKVector", "(" + VECTOR_SIGNATURE + ")V", null, null);
887
        CodeVisitor cv_setPKVector = cv.visitMethod(ACC_PUBLIC, "_persistence_setId", "(" + OBJECT_SIGNATURE + ")V", null, null);
913
        cv_setPKVector.visitVarInsn(ALOAD, 0);
888
        cv_setPKVector.visitVarInsn(ALOAD, 0);
914
        cv_setPKVector.visitVarInsn(ALOAD, 1);
889
        cv_setPKVector.visitVarInsn(ALOAD, 1);
915
        cv_setPKVector.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_primaryKey", VECTOR_SIGNATURE);
890
        cv_setPKVector.visitFieldInsn(PUTFIELD, classDetails.getClassName(), "_persistence_primaryKey", OBJECT_SIGNATURE);
916
        cv_setPKVector.visitInsn(RETURN);
891
        cv_setPKVector.visitInsn(RETURN);
917
        cv_setPKVector.visitMaxs(0 ,0);
892
        cv_setPKVector.visitMaxs(0 ,0);
918
    }
893
    }
(-)jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/jpa/dynamic/DynamicIdentityPolicy.java (-12 / +5 lines)
Lines 18-27 Link Here
18
 ******************************************************************************/
18
 ******************************************************************************/
19
package org.eclipse.persistence.jpa.dynamic;
19
package org.eclipse.persistence.jpa.dynamic;
20
20
21
//javase imports
22
import java.util.Vector;
23
24
//EclipseLink imports
21
//EclipseLink imports
22
import org.eclipse.persistence.internal.identitymaps.CacheId;
25
import org.eclipse.persistence.internal.jpa.CMP3Policy;
23
import org.eclipse.persistence.internal.jpa.CMP3Policy;
26
import org.eclipse.persistence.internal.sessions.AbstractSession;
24
import org.eclipse.persistence.internal.sessions.AbstractSession;
27
25
Lines 35-50 Link Here
35
public class DynamicIdentityPolicy extends CMP3Policy {
33
public class DynamicIdentityPolicy extends CMP3Policy {
36
34
37
    @Override
35
    @Override
38
    public Vector createPkVectorFromKey(Object key, AbstractSession session) {
36
    public Object createPrimaryKeyFromId(Object key, AbstractSession session) {
39
        if (Object[].class.isAssignableFrom(key.getClass())) {
37
        if (key instanceof Object[]) {
40
            Object[] values = (Object[]) key;
38
            return new CacheId((Object[])key);
41
            Vector pk = new Vector(values.length);
42
            for (int index = 0; index < values.length; index++) {
43
                pk.add(values[index]);
44
            }
45
            return pk;
46
        }
39
        }
47
        return super.createPkVectorFromKey(key, session);
40
        return super.createPrimaryKeyFromId(key, session);
48
    }
41
    }
49
42
50
    @Override
43
    @Override

Return to bug 298985