0
votes

When I merge the following detached UserAnswer object that uses composite indexes, the merge fails if and only if I have an index with both a foreign key/mapped entity and a non-foreign key/mapped entity in the object. If the composite index includes only foreign keys or only non-foreign keys, the merge works.

I'm thinking this is a Doctrine2 bug. If not, what am I doing wrong?

Doctrine2 Version: 2.3.4

The controller code below saves a UserAnswer object type, which is described in the following code block:

$entityManager = $this->getDoctrine()->getManager();

$userAnswer = new UserAnswer();
$userAnswer->setUser($this->getUser());
$userAnswer->setAnswerType(1);
$userAnswer->setQuestion($entityManager->getReference('AcmeBundle:Question',1));

$entityManager->detach($userAnswer);
$entityManager->merge($userAnswer);
try {
    $entityManager->flush();
} catch (\Doctrine\DBAL\DBALException $e) {
...

UserAnswer Object:

/**
 * @ORM\Entity
 * @ORM\Table(name="userAnswers")
 */
class UserAnswer
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="User")
     */
    protected $user;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Question")
     */
    protected $question;

    /**
     * @ORM\Id
     * @ORM\Column(name="answer_type", type="integer")
     */
    protected $answer_type;
...

Here's the error I receive:

The identifier answer_type is missing for a query of AcmeBundle\Entity\UserAnswer

500 Internal Server Error - ORMException

Stack Trace

in /vagrant/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php at line 160 -

public static function missingIdentifierField($className, $fieldName)
{
    return new self("The identifier $fieldName is missing for a query of " . $className);
}

public static function overwriteInternalDQLFunctionNotAllowed($functionName)

at ORMException::missingIdentifierField ('Acme\Entity\UserAnswer','answer_type') in /vagrant/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 380 +

at EntityManager ->find('Acme\Entity\UserAnswer', array('user' => '1','question' => '1')) in /vagrant/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 1787 +

at UnitOfWork ->doMerge (object(UserAnswer), array('0000000025cf9503000000006ed40a0a' => object(UserAnswer))) in /vagrant/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php at line 1701 +

at UnitOfWork ->merge (object(UserAnswer)) in /vagrant/Symfony/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php at line 638 +

at EntityManager ->merge (object(UserAnswer)) in /vagrant/Symfony/src/Acme/Controller/UserAnswerController.php at line 23 +

at UserAnswerController ->postAction () at call_user_func_array (array(object(UserAnswerController), 'postAction'), array()) in kernel.root_dir/bootstrap.php.cache at line 2815 +

at HttpKernel ->handleRaw (object(Request), '1') in kernel.root_dir/bootstrap.php.cache at line 2789 +

at HttpKernel->handle (object(Request), '1', true) in kernel.root_dir/bootstrap.php.cache at line 2918 +

at ContainerAwareHttpKernel ->handle (object(Request), '1', true) in kernel.root_dir/bootstrap.php.cache at line 2220 +

at Kernel->handle (object(Request)) in /vagrant/Symfony/web/app_dev.php at line 31 +

This UserAnswer does not produce an error with the above controller code:

/**
 * @ORM\Entity
 * @ORM\Table(name="userAnswers")
 */
class UserAnswer
{
    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="User")
     */
    protected $user;

    /**
     * @ORM\Id
     * @ORM\ManyToOne(targetEntity="Question")
     */
    protected $question;

    /**
     * @ORM\Column(name="answer_type", type="integer")
     */
    protected $answer_type;
...

Nor does this one:

/**
 * @ORM\Entity
 * @ORM\Table(name="userAnswers")
 */
class UserAnswer extends ApiObject
{
    /**
     * @ORM\Id
     * @ORM\Column(name="userid", type="integer")
     */
    protected $userid;

    /**
     * @ORM\Id
     * @ORM\Column(name="question_id", type="integer")
     */
    protected $question_id;

    /**
     * @ORM\Id
     * @ORM\Column(name="answer_type", type="integer")
     */
    protected $answer_type;
...
2

2 Answers

1
votes

This was a Doctrine2 bug and fixed in Doctrine version 2.4.2, which as of this writing hasn't been released. (See http://www.doctrine-project.org/jira/browse/DDC-2645.)

However, the fix is very easy to implement: https://github.com/Exeu/doctrine2/commit/edab2b6a9670dda3127f457205c7720611d6a6c9

0
votes

Looks like this may be related to a known Doctrine Issue and fixed in Version 2.3.4:

http://www.doctrine-project.org/jira/browse/DDC-2645