From 3182ed978e2ebd4d96d5b2f2af6295a446cb2ad9 Mon Sep 17 00:00:00 2001 From: Fay Wang Date: Fri, 8 May 2009 07:48:08 +0000 Subject: [PATCH] OPENJPA-1072: set up foreign key relationship for the relation within an embeddable in an element collection. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@772874 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/meta/ValueMappingImpl.java | 9 ++ .../HandlerCollectionTableFieldStrategy.java | 30 ++++++- .../openjpa/persistence/embed/Book.java | 82 +++++++++++++++++++ .../openjpa/persistence/embed/Listing.java | 66 +++++++++++++++ .../openjpa/persistence/embed/Seller.java | 69 ++++++++++++++++ .../persistence/embed/TestEmbeddable.java | 54 +++++++++--- 6 files changed, 296 insertions(+), 14 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Book.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Listing.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Seller.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java index 17f396bb3..e3f505c91 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java @@ -161,6 +161,15 @@ public class ValueMappingImpl return getValueMappedByMapping().getForeignKey(target); if (target == null) return _fk; + ClassMapping embeddedMeta = (ClassMapping)getEmbeddedMetaData(); + if (embeddedMeta != null) { + FieldMapping[] fields = embeddedMeta.getFieldMappings(); + for (int i = 0; i < fields.length; i++) { + ValueMapping val = fields[i].getValueMapping(); + if (val.getDeclaredTypeMapping() == target) + return val.getForeignKey(); + } + } if (_fk == null && _cols.length == 0) return null; diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java index dd15e30c5..8e615181a 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java @@ -146,18 +146,46 @@ public class HandlerCollectionTableFieldStrategy row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(), sm); + StoreContext ctx = sm.getContext(); ValueMapping elem = field.getElementMapping(); Column order = field.getOrderColumn(); boolean setOrder = field.getOrderColumnIO().isInsertable(order, false); int idx = 0; for (Iterator itr = coll.iterator(); itr.hasNext(); idx++) { - HandlerStrategies.set(elem, itr.next(), store, row, _cols, + Object val = itr.next(); + HandlerStrategies.set(elem, val, store, row, _cols, _io, true); + StateManagerImpl esm = (StateManagerImpl)ctx.getStateManager(val); + if (esm != null) { + boolean isEmbedded = esm.isEmbedded(); + Collection rels = new ArrayList(); + if (isEmbedded) { + getRelations(esm, rels, ctx); + for (Object rel : rels) { + elem.setForeignKey(row, (StateManagerImpl)rel); + } + } + } if (setOrder) row.setInt(order, idx); rm.flushSecondaryRow(row); } } + + private void getRelations(StateManagerImpl sm, Collection rels, + StoreContext ctx) { + FieldMetaData[] fields = sm.getMetaData().getFields(); + for (int i = 0; i < fields.length; i++) { + Object obj = sm.fetch(i); + StateManagerImpl esm = (StateManagerImpl)ctx.getStateManager(obj); + if (esm != null) { + if (!esm.isEmbedded()) + rels.add(esm); + else + getRelations(esm, rels, ctx); + } + } + } public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm) throws SQLException { diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Book.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Book.java new file mode 100644 index 000000000..9d4d13b73 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Book.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.embed; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.*; + +@Entity +@Table(name="BK_EMD") +public class Book { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private int id; + + private long isbn; + + @ElementCollection + @CollectionTable(name="listing") + protected Set listings = new HashSet(); + + public Book(){} + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Book(long isbn){ + this.isbn=isbn; + } + + public long getIsbc() { + return isbn; + } + + public void setIsbc(long isbn) { + this.isbn = isbn; + } + + public Set getListings() { + return listings; + } + + public void setListings(Set listings) { + this.listings = listings; + } + + public void addListing(Listing l){ + listings.add(l); + } + + + public String toString(){ + String res ="Book isbn: " + isbn + "\nListings: "; + for(Listing l : listings){ + res+="\t"+l.toString() + "\n"; + } + return res.substring(0, res.length()-2); + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Listing.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Listing.java new file mode 100644 index 000000000..60c1dc3a4 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Listing.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.embed; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ManyToOne; + + +@Embeddable +public class Listing { + + @ManyToOne(cascade=CascadeType.ALL) + Seller seller; + + Double price; + + String comments; + + public Listing(){} + + public Listing(Seller seller, Double price){ + this.price=price; + this.seller=seller; + } + + public Seller getSeller() { + return seller; + } + + public void setSeller(Seller seller) { + this.seller = seller; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public String getComments() { + return comments; + } + + public void setComments(String comments) { + this.comments = comments; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Seller.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Seller.java new file mode 100644 index 000000000..44025c5e7 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Seller.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.embed; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="SL_EMD") +public class Seller { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private int id; + + private String name; + + public Seller(){ + + } + + public Seller(String n){ + name=n; + } +/* + public Seller(String n, int id){ + name=n; + this.id = id; + } +*/ + public int getId() { + return id; + } +/* + public void setId(int id) { + this.id = id; + } +*/ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String toString(){ + return "Seller id: " + id + " name: " + name; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java index 7ac62d7ac..73834dc50 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java @@ -31,7 +31,7 @@ import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Query; -import junit.framework.Assert; + import org.apache.openjpa.persistence.test.SingleEMFTestCase; public class TestEmbeddable extends SingleEMFTestCase { @@ -83,7 +83,7 @@ public class TestEmbeddable extends SingleEMFTestCase { VicePresident.class, EntityA_Embed_MappedToOne.class, Embed_MappedToOne.class, Embed_MappedToOneCascadeDelete.class, EntityA_Embed_MappedToOneCascadeDelete.class, EntityB2.class, - DROP_TABLES); + Book.class, Listing.class, Seller.class, DROP_TABLES); } public void testEntityA_Coll_String() { @@ -179,6 +179,9 @@ public class TestEmbeddable extends SingleEMFTestCase { updateEntityA_Embed_MappedToOneCascadeDelete(); } + public void testEmbeddableContainingRelationWithGeneratedKey() { + createEmbeddableContainingRelationWithGeneratedKey(); + } /* * Create EntityA_Coll_String */ @@ -1877,34 +1880,34 @@ public class TestEmbeddable extends SingleEMFTestCase { public void assertDepartment1(Department1 d) { int id = d.getDeptId(); Map es = d.getEmpMap(); - Assert.assertEquals(2,es.size()); + assertEquals(2,es.size()); Set keys = es.keySet(); for (Object obj : keys) { Integer empId = (Integer) obj; Employee1 e = es.get(empId); - Assert.assertEquals(empId.intValue(), e.getEmpId()); + assertEquals(empId.intValue(), e.getEmpId()); } } public void assertDepartment2(Department2 d) { int id = d.getDeptId(); Map es = d.getEmpMap(); - Assert.assertEquals(2,es.size()); + assertEquals(2,es.size()); Set keys = es.keySet(); for (EmployeePK2 pk : keys) { Employee2 e = es.get(pk); - Assert.assertEquals(pk, e.getEmpPK()); + assertEquals(pk, e.getEmpPK()); } } public void assertDepartment3(Department3 d) { int id = d.getDeptId(); Map es = d.getEmployees(); - Assert.assertEquals(2,es.size()); + assertEquals(2,es.size()); Set keys = es.keySet(); for (EmployeeName3 key : keys) { Employee3 e = es.get(key); - Assert.assertEquals(key, e.getName()); + assertEquals(key, e.getName()); } } @@ -2010,31 +2013,31 @@ public class TestEmbeddable extends SingleEMFTestCase { public void assertItem1(Item1 item) { int id = item.getId(); Map images = item.getImages(); - Assert.assertEquals(numImagesPerItem, images.size()); + assertEquals(numImagesPerItem, images.size()); } public void assertItem2(Item2 item) { int id = item.getId(); Map images = item.getImages(); - Assert.assertEquals(numImagesPerItem, images.size()); + assertEquals(numImagesPerItem, images.size()); } public void assertItem3(Item3 item) { int id = item.getId(); Map images = item.getImages(); - Assert.assertEquals(numImagesPerItem, images.size()); + assertEquals(numImagesPerItem, images.size()); } public void assertCompany1(Company1 c) { int id = c.getId(); Map organization = c.getOrganization(); - Assert.assertEquals(2,organization.size()); + assertEquals(2,organization.size()); } public void assertCompany2(Company2 c) { int id = c.getId(); Map organization = c.getOrganization(); - Assert.assertEquals(2,organization.size()); + assertEquals(2,organization.size()); } public void assertDivision(Division d) { @@ -2145,4 +2148,29 @@ public class TestEmbeddable extends SingleEMFTestCase { tran.commit(); em.close(); } + public void createEmbeddableContainingRelationWithGeneratedKey() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + + Book b = new Book(1590596455); + Seller bob = new Seller("Bob's books!"); + Seller jim = new Seller("Jim's books!"); + Seller mike = new Seller("Mikes's books!"); + b.addListing(new Listing(bob , 44.15)); + b.addListing(new Listing(jim , 34.15)); + b.addListing(new Listing(mike , 14.15)); + em.getTransaction().begin(); + em.persist(b); + em.getTransaction().commit(); + int id = b.getId(); + em.clear(); + Book b2 = em.find(Book.class, id); + Set listings = b2.getListings(); + for (Listing listing : listings) { + Seller seller = listing.getSeller(); + assertNotNull(seller); + assertTrue(seller.getId() != 0); + } + + } }