当前位置: 首页 > 面试题库 >

忽略了Doctrine生成的SQL的鉴别器部分

梁丘亦
2023-03-14
问题内容

假设以下AbstractPage模型:

/*
 *     @ORM\Entity
 *     @ORM\Table(name="page")
 *     @ORM\InheritanceType("SINGLE_TABLE")
 *     @ORM\DiscriminatorColumn(name="type", type="string")
 *     @ORM\DiscriminatorMap
 *     ({
 *         "page" = "Page",
 *         "link" = "Link"
 *     })
 */

以及以下DQL查询:

SELECT p FROM \Page\Model\AbstractPage

生成的SQL将是:

SELECT ... FROM page p0_ WHERE p0_.type IN ('page', 'link')

现在要问的问题:如何WHERE从该查询中删除该子句。在更复杂的查询中,该WHERE子句的这一部分使得无法使用某些已定义的索引。这可以通过添加type索引来解决,但这会使我的索引变大,我觉得这是没有必要的。

AbstractPage是在继承树的根。因此,我们对表中的所有记录都感兴趣。省略WHERE零件就可以做到这一点。

所以问题是:WHERE在没有必要的情况下,我该如何使Doctrine删除此部分。

谢谢!


问题答案:

这是我能想到的解决方案。想法是扩展一些学说类以添加所需的功能。保持模型不变。

创建扩展SqlWalker的新类(当然是更新名称空间)

<?php

namespace Sad;


use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\SqlWalker;

class CustomSqlWalker extends SqlWalker
{

  const IGNORE_DISCRIMINATION = 'ignoreDiscrimination';

  /**
   * {@inheritdoc}
   */
  public function walkWhereClause($whereClause)
  {
    // Get list of aliases in which discrimination should be ignored
    $ignoreDescription = $this->getQuery()->getHint(self::IGNORE_DISCRIMINATION);
    if ($ignoreDescription !== false) {
      // For each aliases...
      foreach ($this->getQueryComponents() as $k => $component) {
        // ...check if alias is in ignore list
        if (in_array($k, $ignoreDescription)) {
          /** @var $metaObj ClassMetadata */
          $metaObj = $component['metadata'];
          // Update inheritance type to disable discrimination where
          if ($metaObj->isInheritanceTypeSingleTable()) {
            $metaObj->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_NONE);
          }
        }
      }
    }
    return parent::walkWhereClause($whereClause);
  }
}

然后进行查询,您可以执行以下操作:

echo $entityManager->createQuery("SELECT p FROM \Sad\Schema\AbstractPage as p")->getSQL();
// Output: ELECT p0_.id AS id_0, p0_.name AS name_1, p0_.type AS type_2 FROM page p0_ WHERE p0_.type IN ('page', 'link')

$query = $entityManager->createQuery("SELECT p FROM \Sad\Schema\AbstractPage as p");
// Make sure query uses custom walker
$query->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Sad\CustomSqlWalker');
// Specify which aliases should ignore discrimination
$query->setHint(\Sad\CustomSqlWalker::IGNORE_DISCRIMINATION, array('p'));

echo $query->getSQL();
// Output: ELECT p0_.id AS id_0, p0_.name AS name_1, p0_.type AS type_2 FROM page p0_


 类似资料:
  • 我的SINGLE_TAB继承Hibernate配置中出现了一个奇怪的情况,@DiscriminatorColumn似乎被忽略了,而查询总是默认返回到'dtype'列。这就像我在完全没有包含注释(默认列名为'dType')时看到的行为一样。 基本实体: 子类实体: 我还需要访问每个对象中的鉴别器值本身(postType字段)。我仍然有相同的行为,即使我移除它,所以它似乎不是原因。 当我试图通过JPA

  • 我们有一个遗留表,我们不希望通过添加鉴别器列来改变它。有没有可能有不带鉴别器列的tablePerHierarchy。 下面是我的父级和子级代码 @Table(名称=“Shape1”)@Inheritation(策略=InheritanceType.Single_Table)@DiscriminatorColumn(名称=“Discriminator”,discriminatorType=discr

  • 问题内容: 是否可以强制休眠将歧视符列用于继承的继承类型?根据JPA2.0规范,这应该可行,但是我无法在休眠状态下实现。 例: 使用hibernate.hbm2ddl.auto create时,这甚至都不会在表PARENT中创建列TYPE。 我知道InheritanceType.JOINED可以在不定义鉴别符列的情况下工作,但是它是非常无效的,因为在使用鉴别符列中的信息时,休眠需要在父对象和所有子

  • 问题内容: 我正在使用机器人编写一些集成测试。我让机器人打开了一个菜单,它应该从菜单中选择一个选项。除了回车键似乎被忽略。菜单将打开并选择了正确的菜单项,但是如果我按Enter键,则没有采取任何措施。如果我手动按适当的键,它可以完成预期的工作。如果我在非Java应用程序上运行机器人,则其他应用程序将正确响应enter事件。因此,我已经验证我可以正确发送Enter事件,并且Java菜单应该对此做出响

  • 有没有一种方法可以忽略使用mapstruct在此代码示例中第三种方法的映射器的生成?

  • 我有一个与鉴别器列连接的继承映射。 父实体: 附注。我使用的是hibernate 5.0.9.Final。