Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-1156

MappedSuperclass not allowed in the middle of an inheritance hierarchy

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0.4, 2.0.5, 2.1
    • Fix Version/s: 2.1
    • Component/s: Mapping Drivers
    • Security Level: All
    • Labels:
      None

      Description

      For a Class Table Inheritance mapping configuration, an intermediate MappedSuperclass causes a 'noInheritanceOnMappedSuperClass' mapping exception to be thrown by Doctrine\ORM\Mapping\ClassMetadataFactory::loadMetadata() (line 329). However, the MappedSuperclass only contains some simple properties and no inheritance configuration such as DiscriminatorMap or DiscriminatorColumn settings. The MappedSuperclass DOES extend the upper class in the hierarchy that contains this information using annotations, maybe this way it inherits this inheritance configuration.

      The documentation state that a MappedSuperclass can occur in the middle of a inheritance hierarchy.
      http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#mapped-superclasses

      PS: this mapping seemed to be working fine for me using Doctrine 2.0.4 and Doctrine 2.0.5, further inspection showed that this is not the case. Persistence of an Entity fails, Doctrine wants to update a sequence of the persisted Entity, that does not exist as it is a Class Table Inheritance
      PPS: this applies for the 2.1.0-BETA1 release, which is not yet available to create an issue for.

        Activity

        Hide
        Benjamin Eberlei added a comment -

        Fixed, why does this fail on 2.0.4/5? The code doesnt include that exception.

        Show
        Benjamin Eberlei added a comment - Fixed, why does this fail on 2.0.4/5? The code doesnt include that exception.
        Hide
        Menno Holtkamp added a comment -

        Adding the @MappedSuperclass annotation in the middle of an inheritance hierarchy does not throw an Exception anymore and the Schema Tool generates the proper SQL.

        However the problem that was indicated for 2.0.4 and 2.0.5 in the first PS statement of my report remains. It seems that the @SequenceGenerator and in specific the 'sequenceName' setting is ignored for the childs / leafs of the inheritance hierarchy.

        Configuration:

        Project\Entity\Payment\Method.php
        namespace Project\Entity\Payment;
        /**
         * @Entity
         * @Table(schema="public", name="payment_method")
         * @InheritanceType("JOINED")
         * @DiscriminatorColumn(name="discriminator", type="integer")
         * @DiscriminatorMap({
         * "1" = "Project\Entity\Payment\Method\PaymentCard\CreditCard",
         * "2" = "Project\Entity\Payment\Method\PaymentCard\DebitCard",
         * "3" = "Project\Entity\Payment\Method\ElectronicAccount"
         * })
        abstract class Method
        {
        	/**
        	 * The Payment Method's identifier
        	 *
        	 * @var integer
        	 * @Column(name="id",type="integer",nullable=false)
        	 * @Id
        	 * @GeneratedValue(strategy="SEQUENCE")
        	 * @SequenceGenerator(sequenceName="payment_method_id_seq")
        	 */
        	protected $_id;
        }
        
        Project\Entity\Payment\Method\PaymentCard.php
        namespace Project\Entity\Payment\Method;
        /**
         * Project\Entity\Payment\Method\PaymentCard.php
         * Intermediate class that holds common information for PaymentCard Methods
         * No specific database table is required
         *
         * @MappedSuperclass
         */
        abstract class PaymentCard extends Method{}
        

        In the Entities that are defined in the discriminator map, we should leave the @Id annotation behind and to use the same sequence as that is used for the Project\Entity\Payment\Method Entity.

        Project\Entity\Payment\Method\PaymentCard\CreditCard.php
        namespace Project\Entity\Payment\Method\PaymentCard;
        /**
         * CreditCard specific class
         *
         * @Entity
         * @Table(schema="public", name="payment_method_payment_card_credit_card")
         */
        class CreditCard extends PaymentCard
        {
        
        	/**
        	 * The Credit Card Payment Method identifier
        	 *
        	 * Note that no 'Entity-specific' sequence or auto-increment details should be defined, use the inheritance root entity's one
        	 * @link http://www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#class-table-inheritance
        	 * @var integer
        	 * @Column(name="id",type="integer",nullable=false)
        	 * @GeneratedValue(strategy="SEQUENCE")
        	 * @SequenceGenerator(sequenceName="payment_method_id_seq")
        	 */
        	protected $_id;
        }
        

        However, Doctrine fails to persist a Project\Entity\Payment\Method\PaymentCard\CreditCard Entity as it tries to increase the value of the sequence of the CreditCard, which does not exist:

        failed saving Entity, Project\Entity\Payment, SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "payment_method_payment_card_credit_card_id_seq" does not exist LINE 1: SELECT NEXTVAL('payment_method_payment_card_credit_card_id_s...
        

        When I remove the @MappedSuperclass annotation from the intermediate PaymentCard class, this error does not occur and the proper sequence seems to be used.

        Show
        Menno Holtkamp added a comment - Adding the @MappedSuperclass annotation in the middle of an inheritance hierarchy does not throw an Exception anymore and the Schema Tool generates the proper SQL. However the problem that was indicated for 2.0.4 and 2.0.5 in the first PS statement of my report remains. It seems that the @SequenceGenerator and in specific the 'sequenceName' setting is ignored for the childs / leafs of the inheritance hierarchy. Configuration: Project\Entity\Payment\Method.php namespace Project\Entity\Payment; /** * @Entity * @Table(schema= " public " , name= "payment_method" ) * @InheritanceType( "JOINED" ) * @DiscriminatorColumn(name= "discriminator" , type= "integer" ) * @DiscriminatorMap({ * "1" = "Project\Entity\Payment\Method\PaymentCard\CreditCard" , * "2" = "Project\Entity\Payment\Method\PaymentCard\DebitCard" , * "3" = "Project\Entity\Payment\Method\ElectronicAccount" * }) abstract class Method { /** * The Payment Method's identifier * * @ var integer * @Column(name= "id" ,type= "integer" ,nullable= false ) * @Id * @GeneratedValue(strategy= "SEQUENCE" ) * @SequenceGenerator(sequenceName= "payment_method_id_seq" ) */ protected $_id; } Project\Entity\Payment\Method\PaymentCard.php namespace Project\Entity\Payment\Method; /** * Project\Entity\Payment\Method\PaymentCard.php * Intermediate class that holds common information for PaymentCard Methods * No specific database table is required * * @MappedSuperclass */ abstract class PaymentCard extends Method{} In the Entities that are defined in the discriminator map, we should leave the @Id annotation behind and to use the same sequence as that is used for the Project\Entity\Payment\Method Entity. Project\Entity\Payment\Method\PaymentCard\CreditCard.php namespace Project\Entity\Payment\Method\PaymentCard; /** * CreditCard specific class * * @Entity * @Table(schema= " public " , name= "payment_method_payment_card_credit_card" ) */ class CreditCard extends PaymentCard { /** * The Credit Card Payment Method identifier * * Note that no 'Entity-specific' sequence or auto-increment details should be defined, use the inheritance root entity's one * @link http: //www.doctrine-project.org/docs/orm/2.0/en/reference/inheritance-mapping.html#class-table-inheritance * @ var integer * @Column(name= "id" ,type= "integer" ,nullable= false ) * @GeneratedValue(strategy= "SEQUENCE" ) * @SequenceGenerator(sequenceName= "payment_method_id_seq" ) */ protected $_id; } However, Doctrine fails to persist a Project\Entity\Payment\Method\PaymentCard\CreditCard Entity as it tries to increase the value of the sequence of the CreditCard, which does not exist: failed saving Entity, Project\Entity\Payment, SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "payment_method_payment_card_credit_card_id_seq" does not exist LINE 1: SELECT NEXTVAL('payment_method_payment_card_credit_card_id_s... When I remove the @MappedSuperclass annotation from the intermediate PaymentCard class, this error does not occur and the proper sequence seems to be used.
        Hide
        Benjamin Eberlei added a comment -

        Fixed

        Show
        Benjamin Eberlei added a comment - Fixed

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Menno Holtkamp
          • Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: