Skip to content

Commit 206a0a2

Browse files
pduditsPandrex247
authored andcommitted
Merge pull request #4 from pdudits/payara-3700
Payara-3700: Support attribute overrides on shared object in two embeddable fields
1 parent d6443d8 commit 206a0a2

File tree

12 files changed

+432
-16
lines changed

12 files changed

+432
-16
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,8 @@ utils/eclipselink.utils.workbench/logs/
3838
test_*.properties
3939
.sonar
4040
/coverage-report/
41-
/jacoco.out
41+
/jacoco.out
42+
/.project
43+
/eclipselink-src.zip
44+
/plugins/
45+
/jpa/plugins/

foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/CMPPolicy.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 1998, 2014 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
33
* This program and the accompanying materials are made available under the
44
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
55
* which accompanies this distribution.
@@ -14,7 +14,9 @@
1414
* 11/10/2011-2.4 Guy Pelletier
1515
* - 357474: Address primaryKey option from tenant discriminator column
1616
* 14/05/2012-2.4 Guy Pelletier
17-
* - 376603: Provide for table per tenant support for multitenant applications
17+
* - 376603: Provide for table per tenant support for multitenant applications
18+
* 03/23/2016-2.6_WAS Will Dazey
19+
* - 490114: Add support for PersistenceUnitUtil.getIdentifier with nested embeddables in EmbeddedId class
1820
******************************************************************************/
1921
package org.eclipse.persistence.descriptors;
2022

@@ -444,20 +446,31 @@ public Object createPrimaryKeyInstance(Object object, AbstractSession session) {
444446
Object keyObj = object;
445447
KeyElementAccessor accessor = pkElementArray[index];
446448
DatabaseField field = accessor.getDatabaseField();
447-
DatabaseMapping mapping = builder.getMappingForField(field);
449+
DatabaseMapping mapping = builder.getMappingForField(field);
450+
Object nestedKeyInstance = keyInstance;
448451
// With session validation, the mapping shouldn't be null at this
449452
// point, don't bother checking.
450453
if (!mapping.isObjectReferenceMapping() || !usedObjectReferenceMappings.contains(mapping)){
451454
while (mapping.isAggregateObjectMapping()) {
452455
keyObj = mapping.getRealAttributeValueFromObject(keyObj, session);
453-
mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(field);
456+
mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(field);
457+
458+
//Check for embedded Id values
459+
if (mapping.isAggregateMapping()) {
460+
Object nestedObject = mapping.getRealAttributeValueFromObject(nestedKeyInstance, session);
461+
if (nestedObject == null) {
462+
nestedObject = getClassInstance(mapping.getReferenceDescriptor().getJavaClass());
463+
}
464+
mapping.setRealAttributeValueInObject(nestedKeyInstance, nestedObject);
465+
nestedKeyInstance = nestedObject;
466+
}
454467
}
455468
Object fieldValue = mapping.getRealAttributeValueFromObject(keyObj, session);
456469
if (mapping.isObjectReferenceMapping()){
457470
fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstance(fieldValue, session);
458471
usedObjectReferenceMappings.add((ObjectReferenceMapping)mapping);
459472
}
460-
accessor.setValue(keyInstance, fieldValue);
473+
accessor.setValue(nestedKeyInstance, fieldValue);
461474
}
462475
}
463476

foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/ObjectBuilder.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
33
* This program and the accompanying materials are made available under the
44
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
55
* which accompanies this distribution.
@@ -17,6 +17,8 @@
1717
* - 356197: Add new VPD type to MultitenantType
1818
* 11/10/2011-2.4 Guy Pelletier
1919
* - 357474: Address primaryKey option from tenant discriminator column
20+
* 08/07/2016-2.6 Dalia Abo Sheasha
21+
* - 499335: Multiple embeddable fields can't reference same object
2022
******************************************************************************/
2123
package org.eclipse.persistence.internal.descriptors;
2224

@@ -2866,7 +2868,7 @@ public ObjectChangeSet createObjectChangeSet(Object clone, UnitOfWorkChangeSet u
28662868
*/
28672869
public ObjectChangeSet createObjectChangeSet(Object clone, UnitOfWorkChangeSet uowChangeSet, boolean isNew, boolean assignPrimaryKeyIfExisting, AbstractSession session) {
28682870
ObjectChangeSet changes = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(clone);
2869-
if (changes == null) {
2871+
if (changes == null || changes.getDescriptor() != this.descriptor) {
28702872
if (this.descriptor.isAggregateDescriptor()) {
28712873
changes = new AggregateObjectChangeSet(CacheId.EMPTY, this.descriptor, clone, uowChangeSet, isNew);
28722874
} else {

foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/AggregateMapping.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
33
* This program and the accompanying materials are made available under the
44
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
55
* which accompanies this distribution.
@@ -13,6 +13,8 @@
1313
* - 354678: Temp classloader is still being used during metadata processing
1414
* 09 Jan 2013-2.5 Gordon Yorke
1515
* - 397772: JPA 2.1 Entity Graph Support
16+
* 08/07/2016-2.6 Dalia Abo Sheasha
17+
* - 499335: Multiple embeddable fields can't reference same object
1618
******************************************************************************/
1719
package org.eclipse.persistence.mappings;
1820

@@ -366,7 +368,7 @@ public void convertClassNamesToClasses(ClassLoader classLoader) {
366368
try {
367369
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
368370
try {
369-
setReferenceClass(AccessController.doPrivileged(new PrivilegedClassForName(getReferenceClassName(), true, classLoader)));
371+
setReferenceClass(AccessController.doPrivileged(new PrivilegedClassForName(getReferenceClassName(), true, classLoader)));
370372
} catch (PrivilegedActionException exception) {
371373
throw ValidationException.classNotFoundWhileConvertingClassNames(getReferenceClassName(), exception.getException());
372374
}
@@ -984,7 +986,7 @@ public void updateChangeRecord(Object sourceClone, Object newValue, Object oldVa
984986
UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet();
985987
//force comparison change detection to build changeset.
986988
ObjectChangeSet aggregateChangeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(newValue);
987-
if (aggregateChangeSet != null) {
989+
if (aggregateChangeSet != null && aggregateChangeSet.getDescriptor() == referenceDescriptor) {
988990
aggregateChangeSet.clear(true); // old differences must be thrown away because difference is between old value and new value
989991
}
990992
//make sure the listener is initialized

foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/mappings/AggregateObjectMapping.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 1998, 2014 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
33
* This program and the accompanying materials are made available under the
44
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
55
* which accompanies this distribution.
@@ -22,6 +22,8 @@
2222
* 06/03/2013-2.5.1 Guy Pelletier
2323
* - 402380: 3 jpa21/advanced tests failed on server with
2424
* "java.lang.NoClassDefFoundError: org/eclipse/persistence/testing/models/jpa21/advanced/enums/Gender"
25+
* 10/19/2016-2.6 Will Dazey
26+
* - 506168: Make sure nestedTranslation map is new reference when cloned
2527
******************************************************************************/
2628
package org.eclipse.persistence.mappings;
2729

@@ -918,11 +920,15 @@ public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, Map
918920
@Override
919921
public Object clone() {
920922
AggregateObjectMapping mappingObject = (AggregateObjectMapping) super.clone();
921-
923+
922924
Map<String, DatabaseField> aggregateToSourceFields = new HashMap<String, DatabaseField>();
923925
aggregateToSourceFields.putAll(getAggregateToSourceFields());
924926
mappingObject.setAggregateToSourceFields(aggregateToSourceFields);
925927

928+
Map<String, Object[]> nestedTranslations = new HashMap<String, Object[]>();
929+
nestedTranslations.putAll(getNestedFieldTranslations());
930+
mappingObject.setNestedFieldTranslations(nestedTranslations);
931+
926932
return mappingObject;
927933
}
928934

@@ -1160,6 +1166,14 @@ public Map<String, DatabaseField> getAggregateToSourceFields() {
11601166
return aggregateToSourceFields;
11611167
}
11621168

1169+
/**
1170+
* INTERNAL:
1171+
* Return the hashtable that stores the nested field translations.
1172+
*/
1173+
public Map<String, Object[]> getNestedFieldTranslations() {
1174+
return nestedFieldTranslations;
1175+
}
1176+
11631177
/**
11641178
* PUBLIC:
11651179
* The classification type for the attribute this mapping represents
@@ -1869,6 +1883,15 @@ public void setAggregateToSourceFields(Map<String, DatabaseField> aggregateToSou
18691883
aggregateToSourceFields = aggregateToSource;
18701884
}
18711885

1886+
/**
1887+
* INTERNAL:
1888+
* Set the hashtable that stores a field in the source table
1889+
* to a field name in a nested aggregate descriptor.
1890+
*/
1891+
public void setNestedFieldTranslations(Map<String, Object[]> fieldTranslations) {
1892+
nestedFieldTranslations = fieldTranslations;
1893+
}
1894+
18721895
/**
18731896
* PUBLIC:
18741897
* Configure if all the fields in the database row for the aggregate object are NULL,
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2016 IBM Corporation. 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+
* 08/24/2016 - Will Dazey
12+
* - 500145 : Nested Embeddables Test
13+
* 10/19/2016 - Will Dazey
14+
* - 506168 : Nested Embeddables AttributeOverride Test
15+
******************************************************************************/
16+
package org.eclipse.persistence.jpa.embeddable;
17+
18+
import javax.persistence.EntityManager;
19+
import javax.persistence.EntityManagerFactory;
20+
21+
import org.eclipse.persistence.descriptors.ClassDescriptor;
22+
import org.eclipse.persistence.jpa.JpaEntityManager;
23+
import org.eclipse.persistence.jpa.embeddable.model.Address;
24+
import org.eclipse.persistence.jpa.embeddable.model.DeepOrderPK;
25+
import org.eclipse.persistence.jpa.embeddable.model.DeepOrder;
26+
import org.eclipse.persistence.jpa.embeddable.model.Order;
27+
import org.eclipse.persistence.jpa.embeddable.model.OrderPK;
28+
import org.eclipse.persistence.jpa.embeddable.model.Zipcode;
29+
import org.eclipse.persistence.jpa.test.framework.DDLGen;
30+
import org.eclipse.persistence.jpa.test.framework.Emf;
31+
import org.eclipse.persistence.jpa.test.framework.EmfRunner;
32+
import org.junit.Assert;
33+
import org.junit.Test;
34+
import org.junit.runner.RunWith;
35+
36+
@RunWith(EmfRunner.class)
37+
public class TestNestedEmbeddable {
38+
@Emf(createTables = DDLGen.DROP_CREATE, classes = { DeepOrder.class, DeepOrderPK.class, Order.class, OrderPK.class, Address.class, Zipcode.class })
39+
private EntityManagerFactory emf;
40+
41+
@Test
42+
public void persistTest() {
43+
if (emf == null)
44+
return;
45+
EntityManager em = emf.createEntityManager();
46+
try {
47+
em.getTransaction().begin();
48+
Order o = new Order();
49+
50+
String billingZip = "12345";
51+
String shippingZip ="54321";
52+
53+
OrderPK opk = new OrderPK();
54+
opk.setBillingAddress(new Address(new Zipcode(billingZip)));
55+
opk.setShippingAddress(new Address(new Zipcode(shippingZip)));
56+
57+
o.setId(opk);
58+
59+
em.persist(o);
60+
em.getTransaction().commit();
61+
em.clear();
62+
63+
Order foundOrder = em.find(Order.class, o.getId());
64+
65+
Assert.assertNotNull(foundOrder);
66+
67+
Object pk = emf.getPersistenceUnitUtil().getIdentifier(foundOrder);
68+
Assert.assertTrue(pk instanceof OrderPK);
69+
70+
Assert.assertNotNull(((OrderPK)pk).getBillingAddress());
71+
Assert.assertNotNull(((OrderPK)pk).getShippingAddress());
72+
73+
Assert.assertEquals(billingZip,((OrderPK)pk).getBillingAddress().getZipcode().getZip());
74+
Assert.assertEquals(shippingZip,((OrderPK)pk).getShippingAddress().getZipcode().getZip());
75+
} finally {
76+
if (em.getTransaction().isActive()) {
77+
em.getTransaction().rollback();
78+
}
79+
em.close();
80+
}
81+
}
82+
83+
@Test
84+
public void testDeeperEmbeddingMappings() {
85+
if (emf == null)
86+
return;
87+
EntityManager em = emf.createEntityManager();
88+
try {
89+
ClassDescriptor orderDescriptor = ((JpaEntityManager)em).getServerSession().getDescriptor(Order.class);
90+
ClassDescriptor orderpkDescriptor = orderDescriptor.getMappingForAttributeName("id").getReferenceDescriptor();
91+
ClassDescriptor addressDescriptor = orderpkDescriptor.getMappingForAttributeName("billingAddress").getReferenceDescriptor();
92+
ClassDescriptor zipcodeDescriptor = addressDescriptor.getMappingForAttributeName("zipcode").getReferenceDescriptor();
93+
Assert.assertEquals("BILL_ZIP", zipcodeDescriptor.getFields().get(0).getName());
94+
95+
ClassDescriptor deepOrderDescriptor = ((JpaEntityManager)em).getServerSession().getDescriptor(DeepOrder.class);
96+
ClassDescriptor deepOrderpkDescriptor = deepOrderDescriptor.getMappingForAttributeName("id").getReferenceDescriptor();
97+
ClassDescriptor orderpkDescriptor2 = deepOrderpkDescriptor.getMappingForAttributeName("orderpk").getReferenceDescriptor();
98+
ClassDescriptor addressDescriptor2 = orderpkDescriptor2.getMappingForAttributeName("billingAddress").getReferenceDescriptor();
99+
ClassDescriptor zipcodeDescriptor2 = addressDescriptor2.getMappingForAttributeName("zipcode").getReferenceDescriptor();
100+
Assert.assertEquals("deepOverride", zipcodeDescriptor2.getFields().get(0).getName());
101+
102+
} finally {
103+
if (em.getTransaction().isActive()) {
104+
em.getTransaction().rollback();
105+
}
106+
em.close();
107+
}
108+
}
109+
}

jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/AdvancedJPAJunitTest.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
33
* This program and the accompanying materials are made available under the
44
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
55
* which accompanies this distribution.
@@ -23,6 +23,8 @@
2323
* - 328114: @AttributeOverride does not work with nested embeddables having attributes of the same name
2424
* 11/01/2010-2.2 Guy Pelletier
2525
* - 322916: getParameter on Query throws NPE
26+
* 08/07/2016-2.6 Dalia Abo Sheasha
27+
* - 499335: Multiple embeddable fields can't reference same object
2628
******************************************************************************/
2729
package org.eclipse.persistence.testing.tests.jpa.advanced;
2830

@@ -1468,6 +1470,24 @@ public void testSharedEmbeddedAttributeOverrides() {
14681470
beginTransaction(em);
14691471
em.merge(productReRead);
14701472
commitTransaction(em);
1473+
1474+
Product productReRead2 = em.find(Product.class, product.getId());
1475+
productReRead2.setName("OREO");
1476+
productReRead2.setCountryCode("USA");
1477+
String oreoCodeNumber = "762-230-051";
1478+
BarCode barcode = new BarCode(oreoCodeNumber, "USA");
1479+
productReRead2.setBarCode1(barcode);
1480+
productReRead2.setBarCode2(barcode);
1481+
1482+
beginTransaction(em);
1483+
em.merge(productReRead2);
1484+
commitTransaction(em);
1485+
1486+
Product oreoProduct = em.find(Product.class, product.getId());
1487+
BarCode oreoBarCode1 = oreoProduct.getBarCode1();
1488+
BarCode oreoBarCode2 = oreoProduct.getBarCode2();
1489+
assertEquals(oreoCodeNumber, oreoBarCode1.getCodeNumber());
1490+
assertEquals(oreoCodeNumber, oreoBarCode2.getCodeNumber());
14711491
} catch (RuntimeException e) {
14721492
if (isTransactionActive(em)){
14731493
rollbackTransaction(em);

0 commit comments

Comments
 (0)