You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2008/01/05 23:25:19 UTC

svn commit: r609229 - in /cayenne/main/trunk: framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/ framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/ framework/cayenne-jpa-unpublished/src/main/java/or...

Author: aadamchik
Date: Sat Jan  5 14:25:17 2008
New Revision: 609229

URL: http://svn.apache.org/viewvc?rev=609229&view=rev
Log:
CAY-953 JPA: Single Table inheritance
(discriminator column mapping bridging...)

Added:
    cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_10_1_SingleTablePerClassTest.java
Modified:
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaDiscriminatorColumn.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntity.java
    cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_4_PrimaryKeyAndIdentityTest.java

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java?rev=609229&r1=609228&r2=609229&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/bridge/DataMapConverter.java Sat Jan  5 14:25:17 2008
@@ -21,10 +21,12 @@
 
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.Field;
+import java.sql.Types;
 import java.util.Iterator;
 
 import javax.persistence.InheritanceType;
 
+import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.jpa.JpaProviderException;
 import org.apache.cayenne.jpa.conf.EntityMapLoaderContext;
 import org.apache.cayenne.jpa.map.AccessType;
@@ -33,6 +35,7 @@
 import org.apache.cayenne.jpa.map.JpaAttributes;
 import org.apache.cayenne.jpa.map.JpaBasic;
 import org.apache.cayenne.jpa.map.JpaColumn;
+import org.apache.cayenne.jpa.map.JpaDiscriminatorColumn;
 import org.apache.cayenne.jpa.map.JpaEmbeddable;
 import org.apache.cayenne.jpa.map.JpaEmbedded;
 import org.apache.cayenne.jpa.map.JpaEntity;
@@ -737,12 +740,13 @@
 
             JpaEntity entity = path.firstInstanceOf(JpaEntity.class);
             ObjEntity cayenneEntity = targetPath.firstInstanceOf(ObjEntity.class);
+            DbEntity cayennePrimaryTable = cayenneEntity.getDbEntity();
 
             for (JpaSecondaryTable secondaryTable : entity.getSecondaryTables()) {
 
                 // create a relationship between master DbEntity and a secondary
                 // DbEntity...
-                DbEntity cayennePrimaryTable = cayenneEntity.getDbEntity();
+
                 DbEntity cayenneSecondaryTable = cayennePrimaryTable
                         .getDataMap()
                         .getDbEntity(secondaryTable.getName());
@@ -778,6 +782,64 @@
 
                 dbRelationship.setToDependentPK(true);
                 dbRelationship.setToMany(false);
+            }
+
+            // init discriminator column
+            JpaDiscriminatorColumn discriminator = entity.lookupDiscriminatorColumn();
+            if (discriminator != null) {
+
+                if (cayennePrimaryTable.getAttribute(discriminator.getName()) == null) {
+                    DbAttribute dbAttribute = new DbAttribute(discriminator.getName());
+
+                    switch (discriminator.getDiscriminatorType()) {
+                        case CHAR:
+                            dbAttribute.setType(Types.CHAR);
+                            dbAttribute.setMaxLength(1);
+                            break;
+                        case STRING:
+                            dbAttribute.setType(Types.VARCHAR);
+                            dbAttribute.setMaxLength(discriminator.getLength());
+                            break;
+                        case INTEGER:
+                            dbAttribute.setType(Types.INTEGER);
+                            break;
+                    }
+
+                    dbAttribute.setMandatory(false);
+                    cayennePrimaryTable.addAttribute(dbAttribute);
+                }
+
+                String valueString = entity.getDiscriminatorValue();
+                if (valueString != null && valueString.length() > 0) {
+
+                    Object value = null;
+                    switch (discriminator.getDiscriminatorType()) {
+                        case CHAR:
+                            value = valueString.charAt(0);
+                            break;
+                        case STRING:
+                            value = valueString;
+                            break;
+                        case INTEGER:
+                            try {
+                                value = Integer.valueOf(valueString);
+                            }
+                            catch (NumberFormatException e) {
+                                recordConflict(
+                                        path,
+                                        "Invalid integer discriminator value '"
+                                                + valueString);
+                            }
+                            break;
+                    }
+
+                    if (value != null) {
+                        cayenneEntity.setDeclaredQualifier(ExpressionFactory.matchDbExp(
+                                discriminator.getName(),
+                                value));
+                    }
+
+                }
             }
 
             super.onFinishNode(path);

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java?rev=609229&r1=609228&r2=609229&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/EntityMapDefaultsProcessor.java Sat Jan  5 14:25:17 2008
@@ -24,6 +24,7 @@
 import java.util.Collection;
 import java.util.Date;
 
+import javax.persistence.DiscriminatorType;
 import javax.persistence.EnumType;
 import javax.persistence.InheritanceType;
 import javax.persistence.TemporalType;
@@ -36,6 +37,7 @@
 import org.apache.cayenne.jpa.map.JpaBasic;
 import org.apache.cayenne.jpa.map.JpaClassDescriptor;
 import org.apache.cayenne.jpa.map.JpaColumn;
+import org.apache.cayenne.jpa.map.JpaDiscriminatorColumn;
 import org.apache.cayenne.jpa.map.JpaEmbeddable;
 import org.apache.cayenne.jpa.map.JpaEntity;
 import org.apache.cayenne.jpa.map.JpaEntityMap;
@@ -273,6 +275,29 @@
         }
     }
 
+    final class DiscriminatorColumnVisitor extends BaseTreeVisitor {
+
+        @Override
+        public boolean onStartNode(ProjectPath path) {
+
+            JpaDiscriminatorColumn column = (JpaDiscriminatorColumn) path.getObject();
+            if (column.getName() == null) {
+                column.setName("DTYPE");
+            }
+
+            if (column.getDiscriminatorType() == null) {
+                column.setDiscriminatorType(DiscriminatorType.STRING);
+            }
+
+            if (column.getLength() == 0
+                    && column.getDiscriminatorType() == DiscriminatorType.STRING) {
+                column.setLength(31);
+            }
+
+            return false;
+        }
+    }
+
     final class ColumnVisitor extends BaseTreeVisitor {
 
         @Override
@@ -341,6 +366,12 @@
 
     final class EntityVisitor extends AbstractEntityVisitor {
 
+        EntityVisitor() {
+            addChildVisitor(
+                    JpaDiscriminatorColumn.class,
+                    new DiscriminatorColumnVisitor());
+        }
+
         @Override
         public boolean onStartNode(ProjectPath path) {
             if (super.onStartNode(path)) {
@@ -416,6 +447,24 @@
                                         .getName());
                             }
                         }
+                    }
+                }
+            }
+
+            JpaDiscriminatorColumn discriminator = entity.lookupDiscriminatorColumn();
+            if (discriminator != null) {
+
+                if (entity.getDiscriminatorValue() == null) {
+                    switch (discriminator.getDiscriminatorType()) {
+
+                        case STRING:
+                            entity.setDiscriminatorValue(entity.getName());
+                            break;
+                        default:
+                            context.recordConflict(new SimpleValidationFailure(
+                                    entity,
+                                    "Can't guess default discriminator value for non-String discriminator column: "
+                                            + discriminator.getName()));
                     }
                 }
             }

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaDiscriminatorColumn.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaDiscriminatorColumn.java?rev=609229&r1=609228&r2=609229&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaDiscriminatorColumn.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaDiscriminatorColumn.java Sat Jan  5 14:25:17 2008
@@ -39,9 +39,15 @@
     }
 
     public JpaDiscriminatorColumn(DiscriminatorColumn annotation) {
-        name = annotation.name();
+        if (!"".equals(annotation.name())) {
+            name = annotation.name();
+        }
+
+        if (!"".equals(annotation.columnDefinition())) {
+            columnDefinition = annotation.columnDefinition();
+        }
+
         discriminatorType = annotation.discriminatorType();
-        columnDefinition = annotation.columnDefinition();
         length = annotation.length();
     }
 

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntity.java?rev=609229&r1=609228&r2=609229&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/map/JpaEntity.java Sat Jan  5 14:25:17 2008
@@ -256,11 +256,26 @@
         if (table != null) {
             return table;
         }
-        
-        if(superEntity != null) {
+
+        if (superEntity != null) {
             return superEntity.lookupTable();
         }
-        
+
+        return null;
+    }
+
+    /**
+     * Returns a discriminator column for this entity hierarchy.
+     */
+    public JpaDiscriminatorColumn lookupDiscriminatorColumn() {
+        if (discriminatorColumn != null) {
+            return discriminatorColumn;
+        }
+
+        if (superEntity != null) {
+            return superEntity.lookupDiscriminatorColumn();
+        }
+
         return null;
     }
 

Added: cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_10_1_SingleTablePerClassTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_10_1_SingleTablePerClassTest.java?rev=609229&view=auto
==============================================================================
--- cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_10_1_SingleTablePerClassTest.java (added)
+++ cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_10_1_SingleTablePerClassTest.java Sat Jan  5 14:25:17 2008
@@ -0,0 +1,77 @@
+/*****************************************************************
+ *   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.cayenne.jpa.itest.ch2;
+
+import org.apache.cayenne.itest.ItestTableUtils;
+import org.apache.cayenne.itest.jpa.EntityManagerCase;
+
+public class _2_1_10_1_SingleTablePerClassTest extends EntityManagerCase {
+
+    public void testSelectSuper() throws Exception {
+        ItestTableUtils helper = getTableHelper("ST_INHERITANCE");
+        helper.deleteAll();
+        helper.setColumns("id", "objectType", "propertyA", "propertyB", "propertyC");
+        helper.insert(1, "A", "1", null, null);
+        helper.insert(2, "A", "2", null, null);
+        helper.insert(3, "B", "3", "BX", null);
+        helper.insert(4, "C", "4", null, "CX");
+
+//        Query query = getEntityManager().createQuery(
+//                "select a FROM SingleTableInheritanceSuper1 a ORDER BY a.propertyA");
+//        List<?> results = query.getResultList();
+//        assertEquals(4, results.size());
+//
+//        assertEquals(SingleTableInheritanceSuper1.class.getName(), results
+//                .get(0)
+//                .getClass()
+//                .getName());
+//        assertEquals(SingleTableInheritanceSuper1.class.getName(), results
+//                .get(1)
+//                .getClass()
+//                .getName());
+//        assertEquals(SingleTableInheritanceSub1.class.getName(), results
+//                .get(2)
+//                .getClass()
+//                .getName());
+//        assertEquals(SingleTableInheritanceSub2.class.getName(), results
+//                .get(3)
+//                .getClass()
+//                .getName());
+    }
+
+    public void testSelectSub() throws Exception {
+        ItestTableUtils helper = getTableHelper("ST_INHERITANCE");
+        helper.deleteAll();
+        helper.setColumns("id", "objectType", "propertyA", "propertyB", "propertyC");
+        helper.insert(1, "A", "1", null, null);
+        helper.insert(2, "A", "2", null, null);
+        helper.insert(3, "B", "3", "BX", null);
+        helper.insert(4, "C", "4", null, "CX");
+
+//        Query query = getEntityManager().createQuery(
+//                "select a FROM SingleTableInheritanceSub1 a ORDER BY a.propertyA");
+//        List<?> results = query.getResultList();
+//        assertEquals(1, results.size());
+//
+//        assertEquals(SingleTableInheritanceSub1.class.getName(), results
+//                .get(0)
+//                .getClass()
+//                .getName());
+    }
+}

Modified: cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_4_PrimaryKeyAndIdentityTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_4_PrimaryKeyAndIdentityTest.java?rev=609229&r1=609228&r2=609229&view=diff
==============================================================================
--- cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_4_PrimaryKeyAndIdentityTest.java (original)
+++ cayenne/main/trunk/itests/jpa-chapter2/src/test/java/org/apache/cayenne/jpa/itest/ch2/_2_1_4_PrimaryKeyAndIdentityTest.java Sat Jan  5 14:25:17 2008
@@ -33,7 +33,6 @@
 
         try {
             getEntityManager().persist(o1);
-
         }
         catch (IllegalArgumentException e) {
             return;