You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2008/06/10 22:34:53 UTC
svn commit: r666314 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/
Author: ppoddar
Date: Tue Jun 10 13:34:52 2008
New Revision: 666314
URL: http://svn.apache.org/viewvc?rev=666314&view=rev
Log:
OPENJPA-602: Avoid NPE when table-per-class inheritance staregy with an abstract root. See test cases for further details.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/BaseEntity.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/EnglishParagraph.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/FrenchParagraph.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/GermanParagraph.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/TestTablePerClassInheritanceWithAbstractRoot.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translatable.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translation.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyInverseKeyFieldStrategy.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyInverseKeyFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyInverseKeyFieldStrategy.java?rev=666314&r1=666313&r2=666314&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyInverseKeyFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationToManyInverseKeyFieldStrategy.java Tue Jun 10 13:34:52 2008
@@ -133,9 +133,16 @@
elem.setJoinDirection(ValueMapping.JOIN_EXPECTED_INVERSE);
elem.setUseClassCriteria(criteria);
- field.setOrderColumn(finfo.getOrderColumn(field,
- mapped.getForeignKey().getTable(), adapt));
- field.setOrderColumnIO(finfo.getColumnIO());
+ ForeignKey fk = mapped.getForeignKey();
+ /** Foreign key may be null if declared type of the mapped field is
+ * abstract and under table-per-class inheritance strategy will have
+ * no mapped table.
+ */
+ if (fk != null) {
+ field.setOrderColumn(finfo.getOrderColumn(field,
+ fk.getTable(), adapt));
+ field.setOrderColumnIO(finfo.getColumnIO());
+ }
return;
}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/BaseEntity.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/BaseEntity.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/BaseEntity.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/BaseEntity.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,55 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Version;
+
+/**
+ * An abstract base entity class with auto-generated identty and version field.
+ * Used for testing special case of table-per-class inheritance strategy when
+ * the root of persistent inheritance hierarchy is abstract and itself
+ * derives from an abstract MappedSuperClass (i.e. this class).
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@MappedSuperclass
+public abstract class BaseEntity {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @Version
+ private long version;
+
+ public long getId() {
+ return id;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/EnglishParagraph.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/EnglishParagraph.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/EnglishParagraph.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/EnglishParagraph.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import javax.persistence.Entity;
+
+/**
+ * A persistent class derived from an abstract persistent class and
+ * using table-per-concrete-class inheritance strategy.
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@Entity
+public class EnglishParagraph extends Translatable {
+ private String content;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/FrenchParagraph.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/FrenchParagraph.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/FrenchParagraph.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/FrenchParagraph.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import javax.persistence.Entity;
+
+/**
+ * A persistent class derived from an abstract persistent class and
+ * using table-per-concrete-class inheritance strategy.
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@Entity
+public class FrenchParagraph extends Translatable {
+ private String content;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/GermanParagraph.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/GermanParagraph.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/GermanParagraph.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/GermanParagraph.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,45 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import javax.persistence.Entity;
+
+/**
+ * A persistent class derived from an abstract persistent class and
+ * using table-per-concrete-class inheritance strategy.
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@Entity
+public class GermanParagraph extends Translatable {
+ private String content;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/TestTablePerClassInheritanceWithAbstractRoot.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/TestTablePerClassInheritanceWithAbstractRoot.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/TestTablePerClassInheritanceWithAbstractRoot.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/TestTablePerClassInheritanceWithAbstractRoot.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,155 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import java.util.List;
+
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Tests a domain model with following characteristics:
+ * a) A typical bidirectional ManyToOne/OneToMany relation
+ * EntityA references a single instance of EntityB
+ * EntityB references a collection of EntityA
+ * b) EntityB itself is abstract
+ * c) Many concrete subclasses of EntityB exist
+ * d) EntityB uses TABLE_PER_CLASS inheritance strategy, hence no mapping table
+ * exists for EntityB itself.
+ * e) Relation field in EntityA is declared as abstract type EntityB (for which
+ * f) all the domain classes i.e. EntityA, EntityB and all its subclasses is
+ * derived from an abstract MappedSuperClass which holds primary key and
+ * version fields.
+ *
+ * The test addresses a reported error [1] in mapping the above domain model.
+ * The test verifies basic persist, query and delete operations on the domain
+ * model.
+ *
+ * [1] <A HREF="https://issues.apache.org/jira/browse/OPENJPA-602"> OPENJPA-602</A>}
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class TestTablePerClassInheritanceWithAbstractRoot extends
+ SingleEMFTestCase {
+ Class[] UNJOINED_SUBCLASSES = {
+ EnglishParagraph.class,
+ FrenchParagraph.class,
+ GermanParagraph.class};
+
+ public void setUp() {
+ setUp(CLEAR_TABLES,
+ "openjpa.Log", "SQL=TRACE",
+ Translation.class, BaseEntity.class,
+ EnglishParagraph.class, FrenchParagraph.class,
+ GermanParagraph.class, Translatable.class);
+ }
+
+ public void testConsistency() {
+ OpenJPAEntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ /**
+ * Aggregate query operations can not be performed on unjoined
+ * subclasses. Hence all concrete subclasses of abstract base
+ * class is counted separately to count all Translatable instances.
+ */
+ int nTranslatableBefore = count(UNJOINED_SUBCLASSES);
+ int nTranslationBefore = count(Translation.class);
+
+ EnglishParagraph english = new EnglishParagraph();
+ FrenchParagraph french = new FrenchParagraph();
+ GermanParagraph german = new GermanParagraph();
+
+ Translation translation1 = new Translation();
+ Translation translation2 = new Translation();
+ Translation translation3 = new Translation();
+ Translation translation4 = new Translation();
+
+ english.setContent("Hello");
+ french.setContent("Bon jour");
+ german.setContent("Guten Tag");
+
+
+ translation1.setTranslatable(english);
+ translation2.setTranslatable(english);
+ translation3.setTranslatable(french);
+ translation4.setTranslatable(german);
+
+ english.addTranslation(translation1);
+ english.addTranslation(translation2);
+ french.addTranslation(translation3);
+ german.addTranslation(translation4);
+
+ em.persist(translation1);
+ em.persist(translation2);
+ em.persist(translation3);
+ em.persist(translation4);
+ em.getTransaction().commit();
+
+ em.clear();
+
+ int nTranslatableAfter = count(UNJOINED_SUBCLASSES);
+ int nTranslationAfter = count(Translation.class);
+
+ assertEquals(nTranslatableBefore+3, nTranslatableAfter);
+ assertEquals(nTranslationBefore+4, nTranslationAfter);
+
+ /**
+ * Verify that if A refers to B then A must be a member of the set
+ * referred by B
+ */
+ em.getTransaction().begin();
+ List<Translation> result = em.createQuery("SELECT p FROM Translation p")
+ .getResultList();
+ assertTrue(!result.isEmpty());
+ for (Translation translation : result) {
+ assertTrue(translation.getTranslatable()
+ .getTranslations().contains(translation));
+ }
+ em.getTransaction().rollback();
+ }
+
+
+ void linkConsistently(Translation translation, Translatable translatable) {
+ translatable.addTranslation(translation);
+ translation.setTranslatable(translatable);
+ }
+
+ /**
+ * Count the number of instances in the given class by aggregate JPQL query.
+ */
+ public int count(Class c) {
+ OpenJPAEntityManager em = emf.createEntityManager();
+ return ((Number) em.createQuery("SELECT COUNT(p) FROM " +
+ c.getSimpleName() + " p").getSingleResult()).intValue();
+ }
+
+ /**
+ * Count total number of instances of all the given classes by separate JPQL
+ * aggregate query. Useful when a base class has unjoined subclasses.
+ */
+ public int count(Class... classes) {
+ int total = 0;
+ for (Class c:classes) {
+ total += count(c);
+ }
+ return total;
+ }
+
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translatable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translatable.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translatable.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translatable.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,57 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.OneToMany;
+
+/**
+ * An abstract persistent class used as root of inheritance hierarchy and
+ * using table-per-concrete-class inheritance strategy.
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+@Entity
+@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
+public abstract class Translatable extends BaseEntity {
+ @OneToMany(mappedBy="translatable", cascade=CascadeType.PERSIST)
+ private Set<Translation> translations;
+
+ public void addTranslation(Translation t) {
+ if (translations == null)
+ translations = new HashSet<Translation>();
+ translations.add(t);
+ }
+
+ public Set<Translation> getTranslations() {
+ return Collections.unmodifiableSet(translations);
+ }
+}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translation.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translation.java?rev=666314&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translation.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/polymorphic/Translation.java Tue Jun 10 13:34:52 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.inheritance.polymorphic;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="TRANSLATIONS")
+/**
+ * An persistent class that refers to a polymorphic uni-cardinality relation.
+ * The polymorphic relation itself derives from an abstract class that uses
+ * table-per-class inheritance strategy.
+ *
+ * For a more detailed description of the domain model to which this receiver
+ * belongs
+ * @see TestTablePerClassInheritanceWithAbstractRoot
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class Translation extends BaseEntity {
+ @ManyToOne(cascade=CascadeType.PERSIST)
+ private Translatable translatable;
+
+ public Translatable getTranslatable() {
+ return translatable;
+ }
+
+ public void setTranslatable(Translatable translatable) {
+ this.translatable = translatable;
+ }
+}