Bug#500145: Nested Embeddables with matching attribute names overwrite
Signed-off-by: Will Dazey <dazeydev.3@gmail.com>
Reviewed-by: Petros Splinakis <petros.splinakis@oracle.com>
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/TestNestedEmbeddable.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/TestNestedEmbeddable.java
new file mode 100644
index 0000000..28dd000
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/TestNestedEmbeddable.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * 08/24/2016 - Will Dazey
+ * - 500145 : Nested Embeddables Test
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.embeddable;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.eclipse.persistence.jpa.embeddable.model.Address;
+import org.eclipse.persistence.jpa.embeddable.model.Order;
+import org.eclipse.persistence.jpa.embeddable.model.OrderPK;
+import org.eclipse.persistence.jpa.embeddable.model.Zipcode;
+import org.eclipse.persistence.jpa.test.framework.DDLGen;
+import org.eclipse.persistence.jpa.test.framework.Emf;
+import org.eclipse.persistence.jpa.test.framework.EmfRunner;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(EmfRunner.class)
+public class TestNestedEmbeddable {
+ @Emf(createTables = DDLGen.DROP_CREATE, classes = { Order.class, OrderPK.class, Address.class, Zipcode.class })
+ private EntityManagerFactory emf;
+
+ @Test
+ public void persistTest() {
+ if (emf == null)
+ return;
+ EntityManager em = emf.createEntityManager();
+ try {
+ em.getTransaction().begin();
+ Order o = new Order();
+
+ String billingZip = "12345";
+ String shippingZip ="54321";
+
+ OrderPK opk = new OrderPK();
+ opk.setBillingAddress(new Address(new Zipcode(billingZip)));
+ opk.setShippingAddress(new Address(new Zipcode(shippingZip)));
+
+ o.setId(opk);
+
+ em.persist(o);
+ em.getTransaction().commit();
+ em.clear();
+
+ Order foundOrder = em.find(Order.class, o.getId());
+
+ Assert.assertNotNull(foundOrder);
+
+ Object pk = emf.getPersistenceUnitUtil().getIdentifier(foundOrder);
+ Assert.assertTrue(pk instanceof OrderPK);
+
+ Assert.assertNotNull(((OrderPK)pk).getBillingAddress());
+ Assert.assertNotNull(((OrderPK)pk).getShippingAddress());
+
+ Assert.assertEquals(billingZip,((OrderPK)pk).getBillingAddress().getZipcode().getZip());
+ Assert.assertEquals(shippingZip,((OrderPK)pk).getShippingAddress().getZipcode().getZip());
+ } finally {
+ if (em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ em.close();
+ }
+ }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Address.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Address.java
new file mode 100644
index 0000000..9084866
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Address.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * 08/24/2016 - Will Dazey
+ * - 500145 : Nested Embeddables Test
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.embeddable.model;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+
+@Embeddable
+public class Address {
+
+ @Embedded
+ protected Zipcode zipcode;
+
+ public Address() { }
+
+ public Address(Zipcode zipcode) {
+ this.setZipcode(zipcode);
+ }
+
+ public Zipcode getZipcode() {
+ return zipcode;
+ }
+ public void setZipcode(Zipcode zipcode) {
+ this.zipcode = zipcode;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((zipcode == null) ? 0 : zipcode.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Address other = (Address) obj;
+ if (zipcode == null) {
+ if (other.zipcode != null)
+ return false;
+ } else if (!zipcode.equals(other.zipcode))
+ return false;
+ return true;
+ }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Order.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Order.java
new file mode 100644
index 0000000..deeaf9c
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Order.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * 08/24/2016 - Will Dazey
+ * - 500145 : Nested Embeddables Test
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.embeddable.model;
+
+import javax.persistence.AttributeOverride;
+import javax.persistence.AttributeOverrides;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.Version;
+
+@Entity
+@Table(name="CUST_ORDER")
+public class Order {
+
+ @EmbeddedId
+ @AttributeOverrides({
+ @AttributeOverride(name = "billingAddress.zipcode.zip", column = @Column(name = "BILL_ZIP")),
+ @AttributeOverride(name = "shippingAddress.zipcode.zip", column = @Column(name = "SHIP_ZIP"))
+ })
+ private OrderPK id;
+
+ @Version
+ int version;
+
+ public Order() { }
+
+ public OrderPK getId() {
+ return id;
+ }
+
+ public void setId(OrderPK id) {
+ this.id = id;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/OrderPK.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/OrderPK.java
new file mode 100644
index 0000000..20333d4
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/OrderPK.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * 08/24/2016 - Will Dazey
+ * - 500145 : Nested Embeddables Test
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.embeddable.model;
+
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+
+@Embeddable
+public class OrderPK {
+
+ @Embedded
+ private Address billingAddress;
+
+ @Embedded
+ private Address shippingAddress;
+
+ public OrderPK() { }
+
+ public Address getBillingAddress() {
+ return billingAddress;
+ }
+
+ public void setBillingAddress(Address billingAddress) {
+ this.billingAddress = billingAddress;
+ }
+
+ public Address getShippingAddress() {
+ return shippingAddress;
+ }
+
+ public void setShippingAddress(Address shippingAddress) {
+ this.shippingAddress = shippingAddress;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((billingAddress == null) ? 0 : billingAddress.hashCode());
+ result = prime * result + ((shippingAddress == null) ? 0 : shippingAddress.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OrderPK other = (OrderPK) obj;
+ if (billingAddress == null) {
+ if (other.billingAddress != null)
+ return false;
+ } else if (!billingAddress.equals(other.billingAddress))
+ return false;
+ if (shippingAddress == null) {
+ if (other.shippingAddress != null)
+ return false;
+ } else if (!shippingAddress.equals(other.shippingAddress))
+ return false;
+ return true;
+ }
+}
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Zipcode.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Zipcode.java
new file mode 100644
index 0000000..b13e7c9
--- /dev/null
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/embeddable/model/Zipcode.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * 08/24/2016 - Will Dazey
+ * - 500145 : Nested Embeddables Test
+ ******************************************************************************/
+package org.eclipse.persistence.jpa.embeddable.model;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class Zipcode {
+
+ protected String zip;
+
+ public Zipcode() {}
+
+ public Zipcode(String zip) {
+ this.setZip(zip);
+ }
+
+ public String getZip() {
+ return zip;
+ }
+
+ public void setZip(String zip) {
+ this.zip = zip;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((zip == null) ? 0 : zip.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Zipcode other = (Zipcode) obj;
+ if (zip == null) {
+ if (other.zip != null)
+ return false;
+ } else if (!zip.equals(other.zip))
+ return false;
+ return true;
+ }
+}
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/EmbeddedIdAccessor.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/EmbeddedIdAccessor.java
index b99b7c3..423cfce 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/EmbeddedIdAccessor.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/accessors/mappings/EmbeddedIdAccessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016 Oracle and/or its affiliates, IBM Corporation. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
@@ -43,6 +43,8 @@
* - 331386: NPE when mapping chain of 2 multi-column relationships using JPA 2.0 and @EmbeddedId composite PK-FK
* 03/24/2011-2.3 Guy Pelletier
* - 337323: Multi-tenant with shared schema support (part 1)
+ * 08/24/2016-2.6 Will Dazey
+ * - 500145: Nested Embeddables with matching attribute names overwrite
******************************************************************************/
package org.eclipse.persistence.internal.jpa.metadata.accessors.mappings;
@@ -108,15 +110,13 @@
// Update our primary key field with the attribute override field.
// The super class will ensure the correct field is on the metadata
// column.
- m_idFields.put(mappingAccessor.getAttributeName(), overrideField);
+ m_idFields.put(overrideName, overrideField);
}
/**
* INTERNAL:
*/
- protected void addIdFieldFromAccessor(MappingAccessor accessor) {
- String attributeName = accessor.getAttributeName();
-
+ protected void addIdFieldFromAccessor(String attributeName, MappingAccessor accessor) {
if (m_idFields.containsKey(attributeName)) {
// It may be in our id fields map already if an attribute override
// was specified on the embedded mapping. Make sure the existing id
@@ -132,15 +132,16 @@
/**
* INTERNAL:
*/
- protected void addIdFieldsFromAccessors(Collection<MappingAccessor> accessors) {
+ protected void addIdFieldsFromAccessors(String parentAttribute, Collection<MappingAccessor> accessors) {
// Go through all our mappings, the fields from those mappings will
// make up the composite primary key.
for (MappingAccessor accessor : accessors) {
+ String attributeName = (parentAttribute == null) ? accessor.getAttributeName() : parentAttribute + "." + accessor.getAttributeName();
if (accessor.isBasic()) {
- addIdFieldFromAccessor(accessor);
+ addIdFieldFromAccessor(attributeName, accessor);
} else if (accessor.isDerivedIdClass() || accessor.isEmbedded()) {
// Recursively bury down on the embedded or derived id class accessors.
- addIdFieldsFromAccessors(accessor.getReferenceAccessors());
+ addIdFieldsFromAccessors(attributeName, accessor.getReferenceAccessors());
} else {
// EmbeddedId is solely a JPA feature, so we will not allow
// the expansion of attributes for those types of Embeddable
@@ -188,7 +189,7 @@
} else {
// Go through all our mappings, the fields from those mappings will
// make up the composite primary key.
- addIdFieldsFromAccessors(getReferenceAccessors());
+ addIdFieldsFromAccessors(null, getReferenceAccessors());
// Flag this id accessor as a JPA id mapping.
getMapping().setIsJPAId();