Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/DataStoreManyOneIdOwner.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/DataStoreManyOneIdOwner.java?view=auto&rev=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/DataStoreManyOneIdOwner.java
(added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/DataStoreManyOneIdOwner.java
Fri Nov 3 15:15:08 2006
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Version;
+
+@Entity
+public class DataStoreManyOneIdOwner {
+
+ @Id
+ @ManyToOne
+ private DataStoreBasicEntity id;
+
+ private String name;
+
+ @ManyToOne
+ private DataStoreManyOneIdOwner selfRel;
+
+ @Version
+ private Integer optLock;
+
+ public DataStoreBasicEntity getId() {
+ return id;
+ }
+
+ public void setId(DataStoreBasicEntity id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public DataStoreManyOneIdOwner getSelfRel() {
+ return selfRel;
+ }
+
+ public void setSelfRel(DataStoreManyOneIdOwner selfRel) {
+ this.selfRel = selfRel;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/DataStoreManyOneIdOwner.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwner.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwner.java?view=auto&rev=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwner.java
(added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwner.java
Fri Nov 3 15:15:08 2006
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToOne;
+import javax.persistence.Version;
+
+@Entity
+@IdClass(ManyOneCompoundIdOwnerId.class)
+public class ManyOneCompoundIdOwner {
+
+ @Id
+ @GeneratedValue
+ private long longId;
+
+ @Id
+ @ManyToOne
+ private BasicEntity entityId;
+
+ private String name;
+
+ @ManyToOne
+ private ManyOneCompoundIdOwner selfRel;
+
+ @Version
+ private Integer optLock;
+
+ public long getLongId() {
+ return longId;
+ }
+
+ public BasicEntity getEntityId() {
+ return entityId;
+ }
+
+ public void setEntityId(BasicEntity entityId) {
+ this.entityId = entityId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public ManyOneCompoundIdOwner getSelfRel() {
+ return selfRel;
+ }
+
+ public void setSelfRel(ManyOneCompoundIdOwner selfRel) {
+ this.selfRel = selfRel;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwner.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwnerId.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwnerId.java?view=auto&rev=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwnerId.java
(added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneCompoundIdOwnerId.java
Fri Nov 3 15:15:08 2006
@@ -0,0 +1,81 @@
+package org.apache.openjpa.persistence.relations;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Application identity class for: org.apache.openjpa.persistence.relations.ManyOneCompoundIdOwner
+ *
+ * Auto-generated by:
+ * org.apache.openjpa.enhance.ApplicationIdTool
+ */
+public class ManyOneCompoundIdOwnerId implements Serializable {
+ static {
+ // register persistent class in JVM
+ try { Class.forName("org.apache.openjpa.persistence.relations.ManyOneCompoundIdOwner");
}
+ catch(Exception e) {}
+ }
+
+ public long entityId;
+ public long longId;
+
+ public ManyOneCompoundIdOwnerId() {
+ }
+
+ public ManyOneCompoundIdOwnerId(String str) {
+ fromString(str);
+ }
+
+ public String toString() {
+ return String.valueOf(entityId)
+ + "::" + String.valueOf(longId);
+ }
+
+ public int hashCode() {
+ int rs = 17;
+ rs = rs * 37 + (int) (entityId ^ (entityId >>> 32));
+ rs = rs * 37 + (int) (longId ^ (longId >>> 32));
+ return rs;
+ }
+
+ public boolean equals(Object obj) {
+ if(this == obj)
+ return true;
+ if(obj == null || obj.getClass() != getClass())
+ return false;
+
+ ManyOneCompoundIdOwnerId other = (ManyOneCompoundIdOwnerId) obj;
+ return (entityId == other.entityId)
+ && (longId == other.longId);
+ }
+
+ private void fromString(String str) {
+ Tokenizer toke = new Tokenizer(str);
+ str = toke.nextToken();
+ entityId = Long.parseLong(str);
+ str = toke.nextToken();
+ longId = Long.parseLong(str);
+ }
+
+ protected static class Tokenizer {
+ private final String str;
+ private int last;
+
+ public Tokenizer (String str) {
+ this.str = str;
+ }
+
+ public String nextToken () {
+ int next = str.indexOf("::", last);
+ String part;
+ if(next == -1) {
+ part = str.substring(last);
+ last = str.length();
+ } else {
+ part = str.substring(last, next);
+ last = next + 2;
+ }
+ return part;
+ }
+ }
+}
Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneIdOwner.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneIdOwner.java?view=auto&rev=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneIdOwner.java
(added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneIdOwner.java
Fri Nov 3 15:15:08 2006
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Version;
+
+@Entity
+public class ManyOneIdOwner {
+
+ @Id
+ @ManyToOne
+ private BasicEntity id;
+
+ private String name;
+
+ @ManyToOne
+ private ManyOneIdOwner selfRel;
+
+ @Version
+ private Integer optLock;
+
+ public BasicEntity getId() {
+ return id;
+ }
+
+ public void setId(BasicEntity id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public ManyOneIdOwner getSelfRel() {
+ return selfRel;
+ }
+
+ public void setSelfRel(ManyOneIdOwner selfRel) {
+ this.selfRel = selfRel;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ManyOneIdOwner.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestManyOneAsId.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestManyOneAsId.java?view=auto&rev=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestManyOneAsId.java
(added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestManyOneAsId.java
Fri Nov 3 15:15:08 2006
@@ -0,0 +1,397 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.HashMap;
+import java.util.Map;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+
+import junit.framework.TestCase;
+import junit.textui.TestRunner;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+
+/**
+ * Perform basic operations on an entity with a many-one relation as its id
+ * field.
+ *
+ * @author Abe White
+ */
+public class TestManyOneAsId
+ extends TestCase {
+
+ private EntityManagerFactory emf;
+ private long id;
+ private long dsid;
+ private long cid;
+
+ public void setUp() {
+ Map props = new HashMap();
+ props.put("openjpa.MetaDataFactory", "jpa(Types="
+ + BasicEntity.class.getName() + ";"
+ + DataStoreBasicEntity.class.getName() + ";"
+ + ManyOneIdOwner.class.getName() + ";"
+ + DataStoreManyOneIdOwner.class.getName() + ";"
+ + ManyOneCompoundIdOwner.class.getName() + ")");
+ emf = Persistence.createEntityManagerFactory("test", props);
+
+ BasicEntity id1 = new BasicEntity();
+ id1.setName("id1");
+ BasicEntity id2 = new BasicEntity();
+ id2.setName("id2");
+ id1.setRel(id2);
+ id2.setRel(id1);
+ DataStoreBasicEntity dsid1 = new DataStoreBasicEntity();
+ dsid1.setName("dsid1");
+ dsid1.setRel(id1);
+ DataStoreBasicEntity dsid2 = new DataStoreBasicEntity();
+ dsid2.setName("dsid2");
+ dsid2.setRel(id2);
+
+ ManyOneIdOwner parent = new ManyOneIdOwner();
+ parent.setId(id1);
+ parent.setName("parent");
+ ManyOneIdOwner child = new ManyOneIdOwner();
+ child.setId(id2);
+ child.setName("child");
+ parent.setSelfRel(child);
+ DataStoreManyOneIdOwner dsparent = new DataStoreManyOneIdOwner();
+ dsparent.setId(dsid1);
+ dsparent.setName("dsparent");
+ DataStoreManyOneIdOwner dschild = new DataStoreManyOneIdOwner();
+ dschild.setId(dsid2);
+ dschild.setName("dschild");
+ dsparent.setSelfRel(dschild);
+ ManyOneCompoundIdOwner cparent = new ManyOneCompoundIdOwner();
+ cparent.setEntityId(id1);
+ cparent.setName("cparent");
+ ManyOneCompoundIdOwner cchild = new ManyOneCompoundIdOwner();
+ cchild.setEntityId(id2);
+ cchild.setName("cchild");
+ cparent.setSelfRel(cchild);
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.persist(id1);
+ em.persist(id2);
+ em.persist(dsid1);
+ em.persist(dsid2);
+ em.persist(parent);
+ em.persist(child);
+ em.persist(dsparent);
+ em.persist(dschild);
+ em.persist(cparent);
+ em.persist(cchild);
+ em.getTransaction().commit();
+ id = id1.getId();
+ assertRelations(em, parent);
+ OpenJPAEntityManager oem = (OpenJPAEntityManager) em;
+ dsid = (Long) oem.getObjectId(dsid1);
+ assertDataStoreRelations(oem, dsparent);
+ cid = cparent.getLongId();
+ assertCompoundRelations(oem, cparent);
+ em.close();
+ }
+
+ public void tearDown() {
+ if (emf == null)
+ return;
+ try {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.createQuery("delete from ManyOneIdOwner").executeUpdate();
+ em.createQuery("delete from DataStoreManyOneIdOwner").
+ executeUpdate();
+ em.createQuery("delete from ManyOneCompoundIdOwner").
+ executeUpdate();
+ em.createQuery("delete from BasicEntity").executeUpdate();
+ em.createQuery("delete from DataStoreBasicEntity").executeUpdate();
+ em.getTransaction().commit();
+ em.close();
+ emf.close();
+ } catch (Exception e) {
+ }
+ }
+
+ private void assertRelations(EntityManager em, ManyOneIdOwner parent) {
+ assertEquals("parent", parent.getName());
+ BasicEntity id1 = parent.getId();
+ assertNotNull(id1);
+ assertEquals(id, id1.getId());
+ assertEquals("id1", id1.getName());
+ assertTrue(id1 == em.find(BasicEntity.class, id));
+ ManyOneIdOwner child = parent.getSelfRel();
+ assertNotNull(child);
+ assertEquals("child", child.getName());
+ BasicEntity id2 = child.getId();
+ assertNotNull(id2);
+ assertEquals("id2", id2.getName());
+ assertTrue(id2 == em.find(BasicEntity.class, id2.getId()));
+ assertTrue(id2 == id1.getRel());
+ assertTrue(id1 == id2.getRel());
+ assertNull(child.getSelfRel());
+ }
+
+ private void assertDataStoreRelations(OpenJPAEntityManager em,
+ DataStoreManyOneIdOwner dsparent) {
+ assertEquals("dsparent", dsparent.getName());
+ DataStoreBasicEntity dsid1 = dsparent.getId();
+ assertNotNull(dsid1);
+ assertEquals(dsid, ((Long) em.getObjectId(dsid1)).longValue());
+ assertEquals("dsid1", dsid1.getName());
+ assertTrue(dsid1 == em.find(DataStoreBasicEntity.class, dsid));
+ DataStoreManyOneIdOwner dschild = dsparent.getSelfRel();
+ assertNotNull(dschild);
+ assertEquals("dschild", dschild.getName());
+ DataStoreBasicEntity dsid2 = dschild.getId();
+ assertNotNull(dsid2);
+ assertEquals("dsid2", dsid2.getName());
+ assertTrue(dsid2 == em.find(DataStoreBasicEntity.class,
+ em.getObjectId(dsid2)));
+ assertNull(dschild.getSelfRel());
+ }
+
+ private void assertCompoundRelations(OpenJPAEntityManager em,
+ ManyOneCompoundIdOwner cparent) {
+ assertEquals("cparent", cparent.getName());
+ BasicEntity id1 = cparent.getEntityId();
+ assertNotNull(id1);
+ assertEquals(id, id1.getId());
+ assertEquals("id1", id1.getName());
+ assertTrue(id1 == em.find(BasicEntity.class, id));
+ ManyOneCompoundIdOwner cchild = cparent.getSelfRel();
+ assertNotNull(cchild);
+ assertEquals("cchild", cchild.getName());
+ BasicEntity id2 = cchild.getEntityId();
+ assertNotNull(id2);
+ assertEquals("id2", id2.getName());
+ assertTrue(id2 == em.find(BasicEntity.class, id2.getId()));
+ assertNull(cchild.getSelfRel());
+ ManyOneCompoundIdOwnerId oid = (ManyOneCompoundIdOwnerId)
+ em.getObjectId(cparent);
+ assertEquals(id, oid.entityId);
+ }
+
+ public void testRetrieveWithManyOneId() {
+ EntityManager em = emf.createEntityManager();
+ ManyOneIdOwner parent = em.find(ManyOneIdOwner.class, id);
+ assertNotNull(parent);
+ assertRelations(em, parent);
+ em.close();
+ }
+
+ public void testRetrieveWithDataStoreManyOneId() {
+ EntityManager em = emf.createEntityManager();
+ DataStoreManyOneIdOwner dsparent =
+ em.find(DataStoreManyOneIdOwner.class, dsid);
+ assertNotNull(dsparent);
+ assertDataStoreRelations((OpenJPAEntityManager) em, dsparent);
+ em.close();
+ }
+
+ public void testRetrieveWithCompoundManyOneId() {
+ EntityManager em = emf.createEntityManager();
+ ManyOneCompoundIdOwnerId oid = new ManyOneCompoundIdOwnerId();
+ oid.entityId = id;
+ oid.longId = cid;
+ ManyOneCompoundIdOwner cparent =
+ em.find(ManyOneCompoundIdOwner.class, oid);
+ assertNotNull(cparent);
+ assertCompoundRelations((OpenJPAEntityManager) em, cparent);
+ em.close();
+ }
+
+ public void testAttemptToChangeManyOne() {
+ EntityManager em = emf.createEntityManager();
+ ManyOneIdOwner parent = em.find(ManyOneIdOwner.class, id);
+ assertNotNull(parent);
+ assertNotNull(parent.getSelfRel());
+ em.getTransaction().begin();
+ try {
+ parent.setId(parent.getSelfRel().getId());
+ em.getTransaction().commit();
+ fail("Successfully changed id relation.");
+ } catch (Exception e) {
+ // expected
+ if (em.getTransaction().isActive())
+ em.getTransaction().rollback();
+ }
+ em.close();
+ }
+
+ public void testChangeRelationToManyOneOwner() {
+ BasicEntity id3 = new BasicEntity();
+ id3.setName("id3");
+ ManyOneIdOwner child2 = new ManyOneIdOwner();
+ child2.setName("child2");
+ child2.setId(id3);
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.persist(id3);
+ em.persist(child2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ ManyOneIdOwner parent = em.find(ManyOneIdOwner.class, id);
+ assertNotNull(parent);
+ em.getTransaction().begin();
+ parent.setSelfRel(child2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ parent = em.find(ManyOneIdOwner.class, id);
+ child2 = parent.getSelfRel();
+ assertEquals("child2", child2.getName());
+ assertEquals(id3.getId(), child2.getId().getId());
+ em.close();
+ }
+
+ public void testChangeRelationToDataStoreManyOneOwner() {
+ DataStoreBasicEntity dsid3 = new DataStoreBasicEntity();
+ dsid3.setName("dsid3");
+ DataStoreManyOneIdOwner dschild2 = new DataStoreManyOneIdOwner();
+ dschild2.setName("dschild2");
+ dschild2.setId(dsid3);
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.persist(dsid3);
+ em.persist(dschild2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ DataStoreManyOneIdOwner dsparent =
+ em.find(DataStoreManyOneIdOwner.class, dsid);
+ assertNotNull(dsparent);
+ em.getTransaction().begin();
+ dsparent.setSelfRel(dschild2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ dsparent = em.find(DataStoreManyOneIdOwner.class, dsid);
+ dschild2 = dsparent.getSelfRel();
+ assertEquals("dschild2", dschild2.getName());
+ OpenJPAEntityManager oem = (OpenJPAEntityManager) em;
+ assertEquals(oem.getObjectId(dsid3), oem.getObjectId(dschild2.getId()));
+ em.close();
+ }
+
+ public void testChangeRelationToCompoundManyOneOwner() {
+ BasicEntity id3 = new BasicEntity();
+ id3.setName("id3");
+ ManyOneCompoundIdOwner cchild2 = new ManyOneCompoundIdOwner();
+ cchild2.setName("cchild2");
+ cchild2.setEntityId(id3);
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ em.persist(id3);
+ em.persist(cchild2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ ManyOneCompoundIdOwnerId oid = new ManyOneCompoundIdOwnerId();
+ oid.entityId = id;
+ oid.longId = cid;
+ ManyOneCompoundIdOwner cparent = em.find(ManyOneCompoundIdOwner.class,
+ oid);
+ assertNotNull(cparent);
+ em.getTransaction().begin();
+ cparent.setSelfRel(cchild2);
+ em.getTransaction().commit();
+ em.close();
+
+ em = emf.createEntityManager();
+ cparent = em.find(ManyOneCompoundIdOwner.class, oid);
+ cchild2 = cparent.getSelfRel();
+ assertEquals("cchild2", cchild2.getName());
+ assertEquals(id3.getId(), cchild2.getEntityId().getId());
+ em.close();
+ }
+
+ public void testQuery() {
+ EntityManager em = emf.createEntityManager();
+ Query q = em.createQuery("select e from ManyOneIdOwner e "
+ + "where e.id.id = :id");
+ q.setParameter("id", id);
+ ManyOneIdOwner pc = (ManyOneIdOwner) q.getSingleResult();
+ assertNotNull(pc);
+ assertEquals("parent", pc.getName());
+ em.close();
+
+ em = emf.createEntityManager();
+ BasicEntity id1 = em.find(BasicEntity.class, id);
+ assertNotNull(id1);
+ assertEquals("id1", id1.getName());
+ q = em.createQuery("select e from ManyOneIdOwner e where e.id = :id");
+ q.setParameter("id", id1);
+ pc = (ManyOneIdOwner) q.getSingleResult();
+ assertNotNull(pc);
+ assertEquals("parent", pc.getName());
+ em.close();
+ }
+
+ public void testDataStoreQuery() {
+ EntityManager em = emf.createEntityManager();
+ DataStoreBasicEntity dsid1 = em.find(DataStoreBasicEntity.class, dsid);
+ assertNotNull(dsid1);
+ assertEquals("dsid1", dsid1.getName());
+ Query q = em.createQuery("select e from DataStoreManyOneIdOwner e "
+ + "where e.id = :id");
+ q.setParameter("id", dsid1);
+ DataStoreManyOneIdOwner dspc = (DataStoreManyOneIdOwner)
+ q.getSingleResult();
+ assertNotNull(dspc);
+ assertEquals("dsparent", dspc.getName());
+ em.close();
+ }
+
+ public void testCompoundQuery() {
+ EntityManager em = emf.createEntityManager();
+ Query q = em.createQuery("select e from ManyOneCompoundIdOwner e "
+ + "where e.longId = :cid and e.entityId.id = :id");
+ q.setParameter("cid", cid);
+ q.setParameter("id", id);
+ ManyOneCompoundIdOwner pc = (ManyOneCompoundIdOwner)q.getSingleResult();
+ assertNotNull(pc);
+ assertEquals("cparent", pc.getName());
+ em.close();
+
+ em = emf.createEntityManager();
+ BasicEntity id1 = em.find(BasicEntity.class, id);
+ assertNotNull(id1);
+ assertEquals("id1", id1.getName());
+ q = em.createQuery("select e from ManyOneCompoundIdOwner e "
+ + "where e.longId = :cid and e.entityId = :id");
+ q.setParameter("cid", cid);
+ q.setParameter("id", id1);
+ pc = (ManyOneCompoundIdOwner) q.getSingleResult();
+ assertNotNull(pc);
+ assertEquals("cparent", pc.getName());
+ em.close();
+ }
+
+ public static void main(String[] args) {
+ TestRunner.run(TestManyOneAsId.class);
+ }
+}
+
Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java?view=diff&rev=471045&r1=471044&r2=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
(original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceMetaDataDefaults.java
Fri Nov 3 15:15:08 2006
@@ -95,6 +95,7 @@
public PersistenceMetaDataDefaults() {
setCallbackMode(CALLBACK_RETHROW | CALLBACK_ROLLBACK |
CALLBACK_FAIL_FAST);
+ setDataStoreObjectIdFieldUnwrapped(true);
}
/**
Modified: incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml?view=diff&rev=471045&r1=471044&r2=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml (original)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/jpa_overview_pc.xml Fri Nov 3
15:15:08 2006
@@ -684,15 +684,16 @@
<para>
Identity fields must be primitives, primitive wrappers, <classname>
String</classname>s, <classname>Date</classname>s, <classname>
-Timestamp</classname>s, or embeddable types. Notably, other entities instances
-can <emphasis>not</emphasis> be used as identity fields.
+Timestamp</classname>s, or embeddable types.
</para>
<note>
<para>
-For legacy schemas with binary primary key columns, OpenJPA also supports using
-identity fields of type <classname>byte[]</classname>. When you use a
-<classname>byte[]</classname> identity field, you must create an identity class.
-Identity classes are covered below.
+OpenJPA supports entities as identity fields, as the Reference Guide discusses
+in <xref linkend="ref_guide_pc_oid_entitypk"/>. For legacy schemas with binary
+primary key columns, OpenJPA also supports using identity fields of type
+<classname>byte[]</classname>. When you use a <classname>byte[]</classname>
+identity field, you must create an identity class. Identity classes are
+covered below.
</para>
</note>
<warning>
Modified: incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml?view=diff&rev=471045&r1=471044&r2=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml (original)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml Fri Nov
3 15:15:08 2006
@@ -3800,7 +3800,7 @@
<!ATTLIST sequence increment CDATA #IMPLIED>
<!ATTLIST sequence allocate CDATA #IMPLIED>
-<!ELEMENT table (column|index|pk|fk)+>
+<!ELEMENT table (column|index|pk|fk|unique)+>
<!ATTLIST table name CDATA #REQUIRED>
<!ELEMENT column EMPTY>
Modified: incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_pc.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_pc.xml?view=diff&rev=471045&r1=471044&r2=471045
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_pc.xml (original)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_pc.xml Fri Nov 3 15:15:08
2006
@@ -386,14 +386,29 @@
</primary>
</indexterm>
<para>
+OpenJPA makes several enhancements to JPA's standard entity identity.
+ </para>
+ <section id="ref_guide_pc_oid_datastore">
+ <title>
+ Datastore Identity
+ </title>
+ <indexterm zone="ref_guide_pc_oid_datastore">
+ <primary>
+ identity
+ </primary>
+ <secondary>
+ datastore
+ </secondary>
+ </indexterm>
+ <para>
The JPA specification requires you to declare one or more identity fields in
your persistent classes. OpenJPA fully supports this form of object identity,
called <emphasis>application</emphasis> identity. OpenJPA, however, also
supports <emphasis>datastore</emphasis> identity. In datastore identity, you
do
not declare any primary key fields. OpenJPA manages the identity of your
persistent objects for you through a surrogate key in the database.
- </para>
- <para>
+ </para>
+ <para>
You can control how your JPA datastore identity value is generated through
OpenJPA's
<ulink url="../javadoc/org/apache/openjpa/persistence/DataStoreId.html">
@@ -402,17 +417,17 @@
generator</literal> properties that mirror the same-named properties on the
standard <classname>javax.persistence.GeneratedValue</classname> annotation
described in <xref linkend="jpa_overview_meta_id"/> of the JPA Overview.
- </para>
- <para>
+ </para>
+ <para>
To retrieve the identity value of a datastore identity entity, use the
<methodname>OpenJPAEntityManager.getObjectId(Object entity)</methodname>
method. See <xref linkend="ref_guide_runtime_em"/> for more information on
the <classname>OpenJPAEntityManager</classname>.
- </para>
- <example id="ref_guide_pc_oid_datastoreentityex">
- <title>
- JPA Datastore Identity Metadata
- </title>
+ </para>
+ <example id="ref_guide_pc_oid_datastoreentityex">
+ <title>
+ JPA Datastore Identity Metadata
+ </title>
<programlisting>
import org.apache.openjpa.persistence.*;
@@ -423,19 +438,7 @@
... no @Id fields declared ...
}
</programlisting>
- </example>
- <section id="ref_guide_pc_oid_datastore">
- <title>
- Datastore Identity Objects
- </title>
- <indexterm zone="ref_guide_pc_oid">
- <primary>
- identity
- </primary>
- <secondary>
- datastore
- </secondary>
- </indexterm>
+ </example>
<para>
Internally, OpenJPA uses the public
<ulink url="../javadoc/org/apache/openjpa/util/Id.html"><classname>
@@ -452,6 +455,104 @@
primary key value for that object. You can then use this value in calls to
<classname>EntityManager.find</classname> for subsequent lookups of the same
record.
+ </para>
+ </section>
+ <section id="ref_guide_pc_oid_entitypk">
+ <title>
+ Entities as Identity Fields
+ </title>
+ <indexterm zone="ref_guide_pc_oid_entitypk">
+ <primary>
+ identity
+ </primary>
+ <secondary>
+ application
+ </secondary>
+ <tertiary>
+ entity id fields
+ </tertiary>
+ </indexterm>
+ <para>
+The JPA specification limits identity fields to simple types. OpenJPA, however,
+also allows <literal>ManyToOne</literal> and <literal>OneToOne</literal>
+relations to be identity fields. To identify a relation field as an identity
+field, simply annotate it with both the <literal>@ManyToOne</literal> or
+<literal>@OneToOne</literal> relation annotation and the <literal>@Id</literal>
+identity annotation.
+ </para>
+ <para>
+When finding an entity identified by a relation, pass the id of the
+<emphasis>relation</emphasis> to the <methodname>EntityManager.find</methodname>
+method:
+ </para>
+ <example id="ref_guide_pc_oid_entitypk_simplefind">
+ <title>
+ Finding an Entity with an Entity Identity Field
+ </title>
+<programlisting>
+public Delivery createDelivery(EntityManager em, Order order) {
+ Delivery delivery = new Delivery();
+ delivery.setId(o);
+ delivery.setDelivered(new Date());
+ return delivery;
+}
+
+public Delivery findDelivery(EntityManager em, Order order) {
+ // use the identity of the related instance
+ return em.find(Delivery.class, order.getId());
+}
+</programlisting>
+ </example>
+ <para>
+When your entity has multiple identity fields, at least one of which is a
+relation to another entity, you must use an identity class (see
+<xref linkend="jpa_overview_pc_identitycls"/> in the JPA Overview). You cannot
+use an embedded identity object. Identity class fields corresponding to
+entity identity fields should be of the same type as the related entity's
+identity.
+ </para>
+ <example id="ref_guide_pc_oid_entitypk_idcls">
+ <title>
+ Id Class for Entity Identity Fields
+ </title>
+<programlisting>
+@Entity
+public class Order {
+
+ @Id
+ private long id;
+
+ ...
+}
+
+@Entity
+@IdClass(LineItemId.class)
+public class LineItem {
+
+ @Id
+ private int index;
+
+ @Id
+ @ManyToOne
+ private Order order;
+
+ ...
+}
+
+public class LineItemId {
+
+ public int index;
+ public long order; // same type as order's identity
+
+ ...
+}
+</programlisting>
+ </example>
+ <para>
+In the example above, if <classname>Order</classname> had used an identity
+class <classname>OrderId</classname> in place of a simple <classname>long
+</classname> value, then the <literal>LineItemId.order</literal> field
would
+have been of type <classname>OrderId</classname>.
</para>
</section>
<section id="ref_guide_pc_oid_application">
|