openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fa...@apache.org
Subject svn commit: r685042 - in /openjpa: branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ trunk/openjpa-jdbc/src/main/java/org/apache/openj...
Date Tue, 12 Aug 2008 05:10:55 GMT
Author: fancy
Date: Mon Aug 11 22:10:54 2008
New Revision: 685042

URL: http://svn.apache.org/viewvc?rev=685042&view=rev
Log:
OPENJPA-679 java.lang.ArrayIndexOutOfBoundsException may occur when a relation field is annotated as a primary key and a foreign key
Commit patch provided by Fay Wang

Added:
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java
Modified:
    openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java

Modified: openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=685042&r1=685041&r2=685042&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/branches/1.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Mon Aug 11 22:10:54 2008
@@ -18,8 +18,6 @@
  */
 package org.apache.openjpa.jdbc.meta;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,12 +30,12 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
 import org.apache.openjpa.jdbc.schema.Column;
 import org.apache.openjpa.jdbc.schema.ColumnIO;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
@@ -91,6 +89,7 @@
 
     // maps columns to joinables
     private final Map _joinables = Collections.synchronizedMap(new HashMap());
+    private boolean redoPrimaryKeyColumns = false;
 
     /**
      * Constructor. Supply described type and owning repository.
@@ -403,17 +402,25 @@
      * class uses to link to its superclass table.
      */
     public Column[] getPrimaryKeyColumns() {
-        if (_cols.length == 0 && getIdentityType() == ID_APPLICATION
-            && isMapped()) {
-            FieldMapping[] pks = getPrimaryKeyFieldMappings();
-            Collection cols = new ArrayList(pks.length);
-            Column[] fieldCols;
-            for (int i = 0; i < pks.length; i++) {
-                fieldCols = pks[i].getColumns();
-                for (int j = 0; j < fieldCols.length; j++)
-                    cols.add(fieldCols[j]);
+        if (getIdentityType() == ID_APPLICATION && isMapped()) {
+            if (_cols.length == 0 || redoPrimaryKeyColumns) {            
+                FieldMapping[] pks = getPrimaryKeyFieldMappings();
+                Collection cols = new ArrayList(pks.length);
+                Column[] fieldCols;
+                for (int i = 0; i < pks.length; i++) {
+                    fieldCols = pks[i].getColumns();
+                    if (fieldCols.length == 0) {
+                        // some pk columns depends on fk. At this moment, 
+                        // the fk may not contain complete information.
+                        // need to redo the primary key again later on
+                        redoPrimaryKeyColumns = true;
+                        continue;
+                    }
+                    for (int j = 0; j < fieldCols.length; j++)
+                        cols.add(fieldCols[j]);
+                }
+                _cols = (Column[]) cols.toArray(new Column[cols.size()]);
             }
-            _cols = (Column[]) cols.toArray(new Column[cols.size()]);
         }
         return _cols;
     }
@@ -811,9 +818,27 @@
         // recursion, then resolve all fields
         resolveNonRelationMappings();
         FieldMapping[] fms = getFieldMappings();
-        for (int i = 0; i < fms.length; i++)
-            if (fms[i].getDefiningMetaData() == this)
+        for (int i = 0; i < fms.length; i++) {
+            if (fms[i].getDefiningMetaData() == this) {
+                if (fms[i].getForeignKey() != null &&
+                    fms[i].getStrategy() instanceof RelationFieldStrategy) {
+                    // set resolve mode to force this field mapping to be 
+                    // resolved again. The need to resolve again occurs when 
+                    // a primary key is a relation field with the foreign key
+                    // annotation. In this situation, this primary key field
+                    // mapping is resolved during the call to 
+                    // resolveNonRelationMapping. Since it is a relation
+                    // field, the foreign key will be constructed. However, 
+                    // the primary key of the parent entity may not have been 
+                    // resolved yet, resulting in missing informaiton in the fk
+                    fms[i].setResolve(MODE_META); 
+
+                    // set strategy to null to force fk to be re-constructed
+                    fms[i].setStrategy(null, false); 
+                }                
                 fms[i].resolve(MODE_MAPPING);
+            }
+        }
         fms = getDeclaredUnmanagedFieldMappings();
         for (int i = 0; i < fms.length; i++)
             fms[i].resolve(MODE_MAPPING);

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,114 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@IdClass(C.CId.class)
+@Table(name="C4")
+public class C {
+	
+	@Id
+	private String cId;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+    private CM cm;
+
+	@OneToMany(mappedBy="c")
+	private Set<D> ds = new HashSet<D>();
+
+    public C() {
+    }
+    
+    public String getCId() {
+        return cId;
+    }
+
+    public void setCId(String cId) {
+        this.cId = cId;
+    }
+
+    public CM getCm() {
+		return cm;
+	}
+
+	public void setCm(CM cm) {
+		this.cm = cm;
+	}
+
+	public Set<D> getDs() {
+		return ds;
+	}
+
+	public void setDs(Set<D> ds) {
+		this.ds = ds;
+	}
+    
+    public static class CId{
+    	String cId;
+    	CM.CMId  cm;
+    	
+		public String getCId() {
+			return cId;
+		}
+		public void setCId(String id) {
+			cId = id;
+		}
+    	
+		
+		public CM.CMId getCm() {
+			return cm;
+		}
+		public void setCm(CM.CMId cm) {
+			this.cm = cm;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj) return true;
+			if (obj == null || !(obj instanceof CId))
+				return false;
+			
+			CId id = (CId) obj;
+			
+			return (this.getCId() == id.getCId() || (this.getCId() != null &&
+                this.getCId().equals(id.getCId())))
+				&& (this.getCm() == id.getCm() || (this.getCm() != null &&
+                this.getCm().equals(id.getCm())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return ((this.getCId() != null) ? this.getCId().hashCode():0)
+				 ^ ((this.getCm() != null)? this.getCm().hashCode():0);
+		}
+    }
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,120 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@IdClass(CM.CMId.class)
+@Table(name="CM4")
+public class CM {
+	
+	@Id
+    private String cmId;
+
+    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="cm")
+    private Set<C> cs = new HashSet<C>();
+
+    @ManyToOne
+    @ForeignKey
+    @Id
+    private E e;
+    
+    public CM() {
+    }
+
+    public String getCmId() {
+        return cmId;
+    }
+
+    public void setCmId(String cmId) {
+        this.cmId = cmId;
+    }
+
+	public Set<C> getCs() {
+		return cs;
+	}
+
+	public void setCs(Set<C> cs) {
+		this.cs = cs;
+	}
+	
+	public void addC(C c){
+		cs.add(c);
+		c.setCm(this);
+	}
+
+	public E getE() {
+		return e;
+	}
+
+	public void setE(E e) {
+		this.e = e;
+	}
+
+	public static class CMId{
+		private String cmId;
+		private String e;
+		
+		public String getCmId() {
+			return cmId;
+		}
+		public void setCmId(String id) {
+			cmId = id;
+		}
+		
+		public String getE() {
+			return e;
+		}
+		public void setE(String e) {
+			this.e = e;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;			
+			if (obj == null && ! (obj instanceof CMId))
+				return false;
+			CMId id = (CMId) obj;
+			return ( this.getCmId() == id.getCmId() ||
+                (this.getCmId() != null && this.getCmId().equals(id.getCmId())))
+				&& ( this.getE() == id.getE() || (this.getE() != null &&
+                this.getE().equals(id.getE())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getCmId() != null? this.getCmId().hashCode():0) 
+				 ^ (this.getE()!= null ? this.getE().hashCode():0);
+		}
+	}
+
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,124 @@
+/*
+ * 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.relations;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+
+@Entity
+@Table(name="D4")
+@IdClass(D.CId.class)
+public class D {
+
+	@ManyToOne
+	@ForeignKey
+	private C c;
+
+	@Id
+	private String id;
+	
+	private String a;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private VC vc;
+
+	public D() {
+	}
+
+	public String getId() {
+		return id;
+	}
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getA() {
+		return a;
+	}
+
+	public void setA(String a) {
+		this.a = a;
+	}
+
+	public C getC() {
+		return c;
+	}
+
+	public void setC(C c) {
+		this.c = c;
+	}
+
+	public VC getVc() {
+		return vc;
+	}
+
+	public void setVc(VC vc) {
+		this.vc = vc;
+	}
+	
+	
+	public static class CId{
+		private String id;
+		
+		private VC.VCId vc;
+		
+		public VC.VCId getVc() {
+			return vc;
+		}
+		public void setVc(VC.VCId vc) {
+			this.vc = vc;
+		}
+		
+		public String getId() {
+			return id;
+		}
+		public void setId(String id) {
+			this.id = id;
+		}
+		
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null ||  ! (obj instanceof CId))
+				return false;
+			CId id = (CId) obj;
+			return (this.getId() == id.getId() || (this.getId() != null &&
+                this.getId().equals(id.getId())))
+				&& (this.getVc() == id.getVc() || (this.getVc() != null &&
+                this.getVc().equals(id.getVc())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getId() != null ? this.getId().hashCode():0)
+			     ^ (this.getVc() != null ? this.getVc().hashCode():0);
+		}
+				
+	}
+
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,79 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="E4")
+public class E {
+
+	@Id
+	private String eId;
+
+	private String name;
+
+	@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
+	private Set<VCS> vcss = new HashSet<VCS>();
+
+	@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
+	private Set<CM> cms = new HashSet<CM>();
+
+	public E() {
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Set<CM> getCms() {
+		return cms;
+	}
+
+	public void setCms(Set<CM> cms) {
+		this.cms = cms;
+	}
+
+	public String getEId() {
+		return eId;
+	}
+
+	public void setEId(String id) {
+		eId = id;
+	}
+
+	public Set<VCS> getVcss() {
+		return vcss;
+	}
+
+	public void setVcss(Set<VCS> vcss) {
+		this.vcss = vcss;
+	}
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,208 @@
+/*
+ * 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.relations;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import junit.framework.Assert;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+
+public class TestRelationFieldAsPrimaryKeyAndForeignKey 
+    extends SingleEMFTestCase {
+
+	public void setUp() {
+	    setUp(C.class, CM.class, D.class, E.class, VC.class, VCS.class);
+	    
+        EntityManager em = emf.createEntityManager();
+        try {
+            em.getTransaction().begin();
+            List<E> es = (List<E>) em.createQuery(
+            "Select e from E e").getResultList();
+            for (E e : es) 
+                em.remove(e);
+
+            em.getTransaction().commit();
+            em.close();
+        } catch (Exception e) {
+            
+        }
+	    
+	    em = emf.createEntityManager();
+	    em.getTransaction().begin();
+
+	    E e = new E();
+	    e.setEId("E1");
+	    e.setName("E1");
+
+	    VC vc = new VC();
+	    vc.setVcId("VC1");
+
+	    VCS vcset = new VCS();
+	    vcset.setVcsId("VCS1");
+	    vcset.setName("VCSET1");
+	    vcset.addVC(vc);
+	    vcset.setE(e);
+
+	    C c = new C();
+	    c.setCId("C1");
+
+	    CM cm = new CM();
+	    cm.setCmId("CM1");
+	    cm.setE(e);
+	    cm.addC(c);
+
+	    D d = new D();
+	    d.setA("addr");
+	    d.setVc(vc);
+	    d.setId("IM1");
+
+	    em.persist(e);
+	    em.persist(vc);
+	    em.persist(vcset);
+	    em.persist(c);
+	    em.persist(cm);
+	    em.persist(d);
+
+	    em.getTransaction().commit();
+	    em.close();
+	}
+
+	public void testUnboundEntities() {
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    VCS vcSet = new VCS();
+	    vcSet.setVcsId("VCSET2");
+	    vcSet.setName("VCSET2");
+	    try {
+	        em.persist(vcSet);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    VC vc = new VC();
+	    vc.setVcId("VC2");
+	    try {
+	        em.persist(vc);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    CM cm = new CM();
+	    cm.setCmId("CMID2");
+	    try {
+	        em.persist(cm);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    C c = new C();
+	    c.setCId("CID2");
+	    try {
+	        em.persist(c);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.close();
+	}
+
+	public void testQuery() {
+	    EntityManager em = emf.createEntityManager();
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e where e.name='E1'").getResultList();
+	    Assert.assertEquals(1, es.size());
+	    E e = (E) es.get(0);
+	    Assert.assertEquals("E1", e.getName());
+	    Assert.assertEquals(1, e.getVcss().size());
+	    Assert.assertEquals(1, e.getCms().size());
+	    Assert.assertEquals(1, e.getVcss().size());
+
+	    // Get virtual container set and check that it has a reference to the
+	    // ensemble
+	    List<VCS> vcss = (List<VCS>) em.createQuery(
+	        "Select vcset from VCS vcset where vcset.vcsId='VCS1'")
+	        .getResultList();
+	    Assert.assertEquals(1, vcss.size());
+	    Assert.assertEquals(e, ((VCS) vcss.get(0)).getE());
+	    em.close();
+	}
+
+	public void testDeletes() {
+	    // Remove VC set and check that all VCs belonging to that set are
+	    // deleted but not the ensemble itself
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    VCS vcset = (VCS) em.createQuery(
+	        "Select vcset from VCS vcset where vcset.vcsId='VCS1'")
+	        .getSingleResult();
+	    em.remove(vcset);
+	    em.getTransaction().commit();
+
+	    // Get virtualContainer
+	    List<VC> vcs = (List<VC>) em.createQuery(
+	        "Select vc from VC vc where vc.vcId='VC1'")
+	        .getResultList();
+	    Assert.assertEquals(0, vcs.size());
+
+	    // Make sure E and I are still there
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e").getResultList();
+	    Assert.assertEquals(1, es.size());
+	}
+
+	public void tearDown() throws Exception {
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e").getResultList();
+	    for (E e : es) {
+	        em.remove(e);
+	    }
+
+	    em.getTransaction().commit();
+	    em.close();
+	}
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,127 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.relations.VCS.VCSId;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@Table(name="VC4")
+@IdClass(VC.VCId.class)
+
+public class VC {
+
+	@Id
+	private String vcId;
+
+	// @ManyToOne
+	// @ForeignKey
+	// private I i;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private VCS vcs;
+
+	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "vc")
+	private Set<D> ds = new HashSet<D>();
+
+	public VC() {
+	}
+
+	public String getVcId() {
+		return vcId;
+	}
+
+	public void setVcId(String vcId) {
+		this.vcId = vcId;
+	}
+
+	public Set<D> getDs() {
+		return ds;
+	}
+
+	public void setDs(Set<D> ds) {
+		this.ds = ds;
+	}
+
+	public VCS getVcs() {
+		return vcs;
+	}
+
+	public void setVcs(VCS vcs) {
+		this.vcs = vcs;
+	}
+
+	public static class VCId {
+		private String vcId;
+
+		private VCSId vcs;
+
+		public String getVcId() {
+			return vcId;
+		}
+
+		public void setVcId(String vcId) {
+			this.vcId = vcId;
+		}
+
+		public VCSId getVcs() {
+			return vcs;
+		}
+
+		public void setVcs(VCSId vcs) {
+			this.vcs = vcs;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null || !(obj instanceof VCId))
+				return false;
+			VCId id = (VCId) obj;
+			return (this.getVcId() == id.getVcId() ||
+                (this.getVcId() == null &&
+                this.getVcId().equals(id.getVcId()))) && 
+			    (this.getVcs() == id.getVcs() ||
+                (this.getVcs() == null && this
+				.getVcs().equals(id.getVcs())));
+		}
+
+		@Override
+		public int hashCode() {
+			return (this.getVcId() != null ? this.getVcId().hashCode() : 0)
+					^ (this.getVcs() != null ? this.getVcs().hashCode() : 0);
+		}
+	}
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java?rev=685042&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,143 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@Table(name="VCS4")
+@IdClass(VCS.VCSId.class)
+public class VCS {
+
+	@Id
+	private String vcsId;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private E e;
+	
+	@Basic
+	private String name;
+
+	@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy = "vcs")
+	private Set<VC> vcs = new HashSet<VC>();
+
+	public VCS() {
+	}
+
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+
+	public String getVcsId() {
+		return vcsId;
+	}
+
+
+	public void setVcsId(String vcsId) {
+		this.vcsId = vcsId;
+	}
+
+
+	public E getE() {
+		return e;
+	}
+
+
+	public void setE(E e) {
+		this.e = e;
+	}
+
+
+	public Set<VC> getVcs() {
+		return vcs;
+	}
+
+
+	public void setVcs(Set<VC> vcs) {
+		this.vcs = vcs;
+	}
+	
+	public void addVC(VC vc){
+		vcs.add(vc);
+		vc.setVcs(this);
+	}
+	public static class VCSId{
+		private String vcsId;
+		private String e;
+	
+		
+		public String getE() {
+			return e;
+		}
+
+		public void setE(String e) {
+			this.e = e;
+		}
+
+		public String getVcsId() {
+			return vcsId;
+		}
+
+		public void setVcsId(String vcsId) {
+			this.vcsId = vcsId;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null ||  ! (obj instanceof VCSId))
+				return false;
+			VCSId id = (VCSId) obj;
+			return (this.getVcsId() == id.getVcsId() || 
+                (this.getVcsId() != null && 
+                this.getVcsId().equals(id.getVcsId())))
+				&& (this.getE() == id.getE() || (this.getE() != null
+                && this.getE().equals(id.getE())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getVcsId() != null ?this.getVcsId().hashCode():0)
+				^ (this.getE() != null ? this.getE().hashCode():0);
+		}
+	}
+
+}

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=685042&r1=685041&r2=685042&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Mon Aug 11 22:10:54 2008
@@ -18,8 +18,6 @@
  */
 package org.apache.openjpa.jdbc.meta;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -32,12 +30,12 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.lang.StringUtils;
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.Reflection;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.kernel.JDBCStore;
 import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
 import org.apache.openjpa.jdbc.schema.Column;
 import org.apache.openjpa.jdbc.schema.ColumnIO;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
@@ -91,6 +89,7 @@
 
     // maps columns to joinables
     private final Map _joinables = Collections.synchronizedMap(new HashMap());
+    private boolean redoPrimaryKeyColumns = false;
 
     /**
      * Constructor. Supply described type and owning repository.
@@ -418,17 +417,25 @@
      * class uses to link to its superclass table.
      */
     public Column[] getPrimaryKeyColumns() {
-        if (_cols.length == 0 && getIdentityType() == ID_APPLICATION
-            && isMapped()) {
-            FieldMapping[] pks = getPrimaryKeyFieldMappings();
-            Collection cols = new ArrayList(pks.length);
-            Column[] fieldCols;
-            for (int i = 0; i < pks.length; i++) {
-                fieldCols = pks[i].getColumns();
-                for (int j = 0; j < fieldCols.length; j++)
-                    cols.add(fieldCols[j]);
+        if (getIdentityType() == ID_APPLICATION && isMapped()) {
+            if (_cols.length == 0 || redoPrimaryKeyColumns) {            
+                FieldMapping[] pks = getPrimaryKeyFieldMappings();
+                Collection cols = new ArrayList(pks.length);
+                Column[] fieldCols;
+                for (int i = 0; i < pks.length; i++) {
+                    fieldCols = pks[i].getColumns();
+                    if (fieldCols.length == 0) {
+                        // some pk columns depends on fk. At this moment, 
+                        // the fk may not contain complete information.
+                        // need to redo the primary key again later on
+                        redoPrimaryKeyColumns = true;
+                        continue;
+                    }
+                    for (int j = 0; j < fieldCols.length; j++)
+                        cols.add(fieldCols[j]);
+                }
+                _cols = (Column[]) cols.toArray(new Column[cols.size()]);
             }
-            _cols = (Column[]) cols.toArray(new Column[cols.size()]);
         }
         return _cols;
     }
@@ -826,9 +833,27 @@
         // recursion, then resolve all fields
         resolveNonRelationMappings();
         FieldMapping[] fms = getFieldMappings();
-        for (int i = 0; i < fms.length; i++)
-            if (fms[i].getDefiningMetaData() == this)
+        for (int i = 0; i < fms.length; i++) {
+            if (fms[i].getDefiningMetaData() == this) {
+                if (fms[i].getForeignKey() != null &&
+                    fms[i].getStrategy() instanceof RelationFieldStrategy) {
+                    // set resolve mode to force this field mapping to be 
+                    // resolved again. The need to resolve again occurs when 
+                    // a primary key is a relation field with the foreign key
+                    // annotation. In this situation, this primary key field
+                    // mapping is resolved during the call to 
+                    // resolveNonRelationMapping. Since it is a relation
+                    // field, the foreign key will be constructed. However, 
+                    // the primary key of the parent entity may not have been 
+                    // resolved yet, resulting in missing informaiton in the fk
+                    fms[i].setResolve(MODE_META); 
+
+                    // set strategy to null to force fk to be re-constructed
+                    fms[i].setStrategy(null, false); 
+                }                
                 fms[i].resolve(MODE_MAPPING);
+            }
+        }
         fms = getDeclaredUnmanagedFieldMappings();
         for (int i = 0; i < fms.length; i++)
             fms[i].resolve(MODE_MAPPING);

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/C.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,114 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@IdClass(C.CId.class)
+@Table(name="C4")
+public class C {
+	
+	@Id
+	private String cId;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+    private CM cm;
+
+	@OneToMany(mappedBy="c")
+	private Set<D> ds = new HashSet<D>();
+
+    public C() {
+    }
+    
+    public String getCId() {
+        return cId;
+    }
+
+    public void setCId(String cId) {
+        this.cId = cId;
+    }
+
+    public CM getCm() {
+		return cm;
+	}
+
+	public void setCm(CM cm) {
+		this.cm = cm;
+	}
+
+	public Set<D> getDs() {
+		return ds;
+	}
+
+	public void setDs(Set<D> ds) {
+		this.ds = ds;
+	}
+    
+    public static class CId{
+    	String cId;
+    	CM.CMId  cm;
+    	
+		public String getCId() {
+			return cId;
+		}
+		public void setCId(String id) {
+			cId = id;
+		}
+    	
+		
+		public CM.CMId getCm() {
+			return cm;
+		}
+		public void setCm(CM.CMId cm) {
+			this.cm = cm;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj) return true;
+			if (obj == null || !(obj instanceof CId))
+				return false;
+			
+			CId id = (CId) obj;
+			
+			return (this.getCId() == id.getCId() || (this.getCId() != null &&
+                this.getCId().equals(id.getCId())))
+				&& (this.getCm() == id.getCm() || (this.getCm() != null &&
+                this.getCm().equals(id.getCm())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return ((this.getCId() != null) ? this.getCId().hashCode():0)
+				 ^ ((this.getCm() != null)? this.getCm().hashCode():0);
+		}
+    }
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/CM.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,120 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@IdClass(CM.CMId.class)
+@Table(name="CM4")
+public class CM {
+	
+	@Id
+    private String cmId;
+
+    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="cm")
+    private Set<C> cs = new HashSet<C>();
+
+    @ManyToOne
+    @ForeignKey
+    @Id
+    private E e;
+    
+    public CM() {
+    }
+
+    public String getCmId() {
+        return cmId;
+    }
+
+    public void setCmId(String cmId) {
+        this.cmId = cmId;
+    }
+
+	public Set<C> getCs() {
+		return cs;
+	}
+
+	public void setCs(Set<C> cs) {
+		this.cs = cs;
+	}
+	
+	public void addC(C c){
+		cs.add(c);
+		c.setCm(this);
+	}
+
+	public E getE() {
+		return e;
+	}
+
+	public void setE(E e) {
+		this.e = e;
+	}
+
+	public static class CMId{
+		private String cmId;
+		private String e;
+		
+		public String getCmId() {
+			return cmId;
+		}
+		public void setCmId(String id) {
+			cmId = id;
+		}
+		
+		public String getE() {
+			return e;
+		}
+		public void setE(String e) {
+			this.e = e;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;			
+			if (obj == null && ! (obj instanceof CMId))
+				return false;
+			CMId id = (CMId) obj;
+			return ( this.getCmId() == id.getCmId() ||
+                (this.getCmId() != null && this.getCmId().equals(id.getCmId())))
+				&& ( this.getE() == id.getE() || (this.getE() != null &&
+                this.getE().equals(id.getE())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getCmId() != null? this.getCmId().hashCode():0) 
+				 ^ (this.getE()!= null ? this.getE().hashCode():0);
+		}
+	}
+
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/D.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,124 @@
+/*
+ * 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.relations;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+
+@Entity
+@Table(name="D4")
+@IdClass(D.CId.class)
+public class D {
+
+	@ManyToOne
+	@ForeignKey
+	private C c;
+
+	@Id
+	private String id;
+	
+	private String a;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private VC vc;
+
+	public D() {
+	}
+
+	public String getId() {
+		return id;
+	}
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getA() {
+		return a;
+	}
+
+	public void setA(String a) {
+		this.a = a;
+	}
+
+	public C getC() {
+		return c;
+	}
+
+	public void setC(C c) {
+		this.c = c;
+	}
+
+	public VC getVc() {
+		return vc;
+	}
+
+	public void setVc(VC vc) {
+		this.vc = vc;
+	}
+	
+	
+	public static class CId{
+		private String id;
+		
+		private VC.VCId vc;
+		
+		public VC.VCId getVc() {
+			return vc;
+		}
+		public void setVc(VC.VCId vc) {
+			this.vc = vc;
+		}
+		
+		public String getId() {
+			return id;
+		}
+		public void setId(String id) {
+			this.id = id;
+		}
+		
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null ||  ! (obj instanceof CId))
+				return false;
+			CId id = (CId) obj;
+			return (this.getId() == id.getId() || (this.getId() != null &&
+                this.getId().equals(id.getId())))
+				&& (this.getVc() == id.getVc() || (this.getVc() != null &&
+                this.getVc().equals(id.getVc())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getId() != null ? this.getId().hashCode():0)
+			     ^ (this.getVc() != null ? this.getVc().hashCode():0);
+		}
+				
+	}
+
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/E.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,79 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="E4")
+public class E {
+
+	@Id
+	private String eId;
+
+	private String name;
+
+	@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
+	private Set<VCS> vcss = new HashSet<VCS>();
+
+	@OneToMany(cascade = CascadeType.ALL, mappedBy = "e")
+	private Set<CM> cms = new HashSet<CM>();
+
+	public E() {
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Set<CM> getCms() {
+		return cms;
+	}
+
+	public void setCms(Set<CM> cms) {
+		this.cms = cms;
+	}
+
+	public String getEId() {
+		return eId;
+	}
+
+	public void setEId(String id) {
+		eId = id;
+	}
+
+	public Set<VCS> getVcss() {
+		return vcss;
+	}
+
+	public void setVcss(Set<VCS> vcss) {
+		this.vcss = vcss;
+	}
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationFieldAsPrimaryKeyAndForeignKey.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,208 @@
+/*
+ * 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.relations;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import junit.framework.Assert;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+
+public class TestRelationFieldAsPrimaryKeyAndForeignKey 
+    extends SingleEMFTestCase {
+
+	public void setUp() {
+	    setUp(C.class, CM.class, D.class, E.class, VC.class, VCS.class);
+	    
+        EntityManager em = emf.createEntityManager();
+        try {
+            em.getTransaction().begin();
+            List<E> es = (List<E>) em.createQuery(
+            "Select e from E e").getResultList();
+            for (E e : es) 
+                em.remove(e);
+
+            em.getTransaction().commit();
+            em.close();
+        } catch (Exception e) {
+            
+        }
+	    
+	    em = emf.createEntityManager();
+	    em.getTransaction().begin();
+
+	    E e = new E();
+	    e.setEId("E1");
+	    e.setName("E1");
+
+	    VC vc = new VC();
+	    vc.setVcId("VC1");
+
+	    VCS vcset = new VCS();
+	    vcset.setVcsId("VCS1");
+	    vcset.setName("VCSET1");
+	    vcset.addVC(vc);
+	    vcset.setE(e);
+
+	    C c = new C();
+	    c.setCId("C1");
+
+	    CM cm = new CM();
+	    cm.setCmId("CM1");
+	    cm.setE(e);
+	    cm.addC(c);
+
+	    D d = new D();
+	    d.setA("addr");
+	    d.setVc(vc);
+	    d.setId("IM1");
+
+	    em.persist(e);
+	    em.persist(vc);
+	    em.persist(vcset);
+	    em.persist(c);
+	    em.persist(cm);
+	    em.persist(d);
+
+	    em.getTransaction().commit();
+	    em.close();
+	}
+
+	public void testUnboundEntities() {
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    VCS vcSet = new VCS();
+	    vcSet.setVcsId("VCSET2");
+	    vcSet.setName("VCSET2");
+	    try {
+	        em.persist(vcSet);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    VC vc = new VC();
+	    vc.setVcId("VC2");
+	    try {
+	        em.persist(vc);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    CM cm = new CM();
+	    cm.setCmId("CMID2");
+	    try {
+	        em.persist(cm);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.getTransaction().begin();
+	    C c = new C();
+	    c.setCId("CID2");
+	    try {
+	        em.persist(c);
+	        em.getTransaction().commit();
+	        Assert.fail("didn't throw expected PersistenceException");
+	    } catch (Exception e) {
+	        // test pass
+	    } finally {
+	        if (em.getTransaction().isActive())
+	            em.getTransaction().rollback();
+	    }
+
+	    em.close();
+	}
+
+	public void testQuery() {
+	    EntityManager em = emf.createEntityManager();
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e where e.name='E1'").getResultList();
+	    Assert.assertEquals(1, es.size());
+	    E e = (E) es.get(0);
+	    Assert.assertEquals("E1", e.getName());
+	    Assert.assertEquals(1, e.getVcss().size());
+	    Assert.assertEquals(1, e.getCms().size());
+	    Assert.assertEquals(1, e.getVcss().size());
+
+	    // Get virtual container set and check that it has a reference to the
+	    // ensemble
+	    List<VCS> vcss = (List<VCS>) em.createQuery(
+	        "Select vcset from VCS vcset where vcset.vcsId='VCS1'")
+	        .getResultList();
+	    Assert.assertEquals(1, vcss.size());
+	    Assert.assertEquals(e, ((VCS) vcss.get(0)).getE());
+	    em.close();
+	}
+
+	public void testDeletes() {
+	    // Remove VC set and check that all VCs belonging to that set are
+	    // deleted but not the ensemble itself
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    VCS vcset = (VCS) em.createQuery(
+	        "Select vcset from VCS vcset where vcset.vcsId='VCS1'")
+	        .getSingleResult();
+	    em.remove(vcset);
+	    em.getTransaction().commit();
+
+	    // Get virtualContainer
+	    List<VC> vcs = (List<VC>) em.createQuery(
+	        "Select vc from VC vc where vc.vcId='VC1'")
+	        .getResultList();
+	    Assert.assertEquals(0, vcs.size());
+
+	    // Make sure E and I are still there
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e").getResultList();
+	    Assert.assertEquals(1, es.size());
+	}
+
+	public void tearDown() throws Exception {
+	    EntityManager em = emf.createEntityManager();
+	    em.getTransaction().begin();
+	    List<E> es = (List<E>) em.createQuery(
+	        "Select e from E e").getResultList();
+	    for (E e : es) {
+	        em.remove(e);
+	    }
+
+	    em.getTransaction().commit();
+	    em.close();
+	}
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VC.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,127 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.relations.VCS.VCSId;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@Table(name="VC4")
+@IdClass(VC.VCId.class)
+
+public class VC {
+
+	@Id
+	private String vcId;
+
+	// @ManyToOne
+	// @ForeignKey
+	// private I i;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private VCS vcs;
+
+	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "vc")
+	private Set<D> ds = new HashSet<D>();
+
+	public VC() {
+	}
+
+	public String getVcId() {
+		return vcId;
+	}
+
+	public void setVcId(String vcId) {
+		this.vcId = vcId;
+	}
+
+	public Set<D> getDs() {
+		return ds;
+	}
+
+	public void setDs(Set<D> ds) {
+		this.ds = ds;
+	}
+
+	public VCS getVcs() {
+		return vcs;
+	}
+
+	public void setVcs(VCS vcs) {
+		this.vcs = vcs;
+	}
+
+	public static class VCId {
+		private String vcId;
+
+		private VCSId vcs;
+
+		public String getVcId() {
+			return vcId;
+		}
+
+		public void setVcId(String vcId) {
+			this.vcId = vcId;
+		}
+
+		public VCSId getVcs() {
+			return vcs;
+		}
+
+		public void setVcs(VCSId vcs) {
+			this.vcs = vcs;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null || !(obj instanceof VCId))
+				return false;
+			VCId id = (VCId) obj;
+			return (this.getVcId() == id.getVcId() ||
+                (this.getVcId() == null &&
+                this.getVcId().equals(id.getVcId()))) && 
+			    (this.getVcs() == id.getVcs() ||
+                (this.getVcs() == null && this
+				.getVcs().equals(id.getVcs())));
+		}
+
+		@Override
+		public int hashCode() {
+			return (this.getVcId() != null ? this.getVcId().hashCode() : 0)
+					^ (this.getVcs() != null ? this.getVcs().hashCode() : 0);
+		}
+	}
+}

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java?rev=685042&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/VCS.java Mon Aug 11 22:10:54 2008
@@ -0,0 +1,143 @@
+/*
+ * 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.relations;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.jdbc.ForeignKey;
+
+@Entity
+@Table(name="VCS4")
+@IdClass(VCS.VCSId.class)
+public class VCS {
+
+	@Id
+	private String vcsId;
+
+	@ManyToOne
+	@ForeignKey
+	@Id
+	private E e;
+	
+	@Basic
+	private String name;
+
+	@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy = "vcs")
+	private Set<VC> vcs = new HashSet<VC>();
+
+	public VCS() {
+	}
+
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+
+	public String getVcsId() {
+		return vcsId;
+	}
+
+
+	public void setVcsId(String vcsId) {
+		this.vcsId = vcsId;
+	}
+
+
+	public E getE() {
+		return e;
+	}
+
+
+	public void setE(E e) {
+		this.e = e;
+	}
+
+
+	public Set<VC> getVcs() {
+		return vcs;
+	}
+
+
+	public void setVcs(Set<VC> vcs) {
+		this.vcs = vcs;
+	}
+	
+	public void addVC(VC vc){
+		vcs.add(vc);
+		vc.setVcs(this);
+	}
+	public static class VCSId{
+		private String vcsId;
+		private String e;
+	
+		
+		public String getE() {
+			return e;
+		}
+
+		public void setE(String e) {
+			this.e = e;
+		}
+
+		public String getVcsId() {
+			return vcsId;
+		}
+
+		public void setVcsId(String vcsId) {
+			this.vcsId = vcsId;
+		}
+
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null ||  ! (obj instanceof VCSId))
+				return false;
+			VCSId id = (VCSId) obj;
+			return (this.getVcsId() == id.getVcsId() || 
+                (this.getVcsId() != null && 
+                this.getVcsId().equals(id.getVcsId())))
+				&& (this.getE() == id.getE() || (this.getE() != null
+                && this.getE().equals(id.getE())));
+		}
+		
+		@Override
+		public int hashCode() {
+			return (this.getVcsId() != null ?this.getVcsId().hashCode():0)
+				^ (this.getE() != null ? this.getE().hashCode():0);
+		}
+	}
+
+}



Mime
View raw message