首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无主键实体的Symfony原理模型

无主键实体的Symfony原理模型
EN

Stack Overflow用户
提问于 2011-12-08 18:52:47
回答 2查看 10.4K关注 0票数 3

在重新构建web应用程序时,我正在使用遗留数据库。我想使用Symfony2.x,它显然具有Doctrine作为ORM。

我有大约50个没有主键的(mysql)表。当我尝试生成模型时,它不允许我这样做,并抛出一个异常"No Primary Key on ... table“。

我必须在表上有主键才能使用Doctrine吗?或者有什么方法可以绕过它吗?

任何帮助都是最好的。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-08 20:01:21

原理要求每个实体类都有一个标识符/主键。

看看这个页面:http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys

票数 1
EN

Stack Overflow用户

发布于 2013-04-02 22:26:02

Doctrine要求有一个标识符/主键。看看这个页面:http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys

但是有一种方法可以从没有主键的表中生成映射和实体。没有主键的表是一种不常见且糟糕的数据库设计,但在遗留数据库的情况下也存在这种情况。

解决方案

注释:下面的所有参考文献都指的是Doctrin2.0

找到文件DatabaseDriver.php (在Doctrine/ORM/Mapping/Driver/DatabaseDriver.php)

  • Find中为reverseEngineerMappingFromDatabase.
  1. 按照下面的说明修改代码。

原始代码是:

代码语言:javascript
复制
private function reverseEngineerMappingFromDatabase()
    {
        if ($this->tables !== null) {
            return;
        }

        $tables = array();

        foreach ($this->_sm->listTableNames() as $tableName) {
            $tables[$tableName] = $this->_sm->listTableDetails($tableName);
        }

        $this->tables = $this->manyToManyTables = $this->classToTableNames = array();
        foreach ($tables as $tableName => $table) {
            /* @var $table \Doctrine\DBAL\Schema\Table */
            if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
                $foreignKeys = $table->getForeignKeys();
            } else {
                $foreignKeys = array();
            }

            $allForeignKeyColumns = array();
            foreach ($foreignKeys as $foreignKey) {
                $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
            }

            if ( ! $table->hasPrimaryKey()) {
                throw new MappingException(
                    "Table " . $table->getName() . " has no primary key. Doctrine does not ".
                    "support reverse engineering from tables that don't have a primary key."
                );
            }

            $pkColumns = $table->getPrimaryKey()->getColumns();
            sort($pkColumns);
            sort($allForeignKeyColumns);

            if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
                $this->manyToManyTables[$tableName] = $table;
            } else {
                // lower-casing is necessary because of Oracle Uppercase Tablenames,
                // assumption is lower-case + underscore separated.
                $className = $this->getClassNameForTable($tableName);
                $this->tables[$tableName] = $table;
                $this->classToTableNames[$className] = $tableName;
            }
        }
    }

修改后的代码为:

代码语言:javascript
复制
private function reverseEngineerMappingFromDatabase()
    {
        if ($this->tables !== null) {
            return;
        }

        $tables = array();

        foreach ($this->_sm->listTableNames() as $tableName) {
            $tables[$tableName] = $this->_sm->listTableDetails($tableName);
        }

        $this->tables = $this->manyToManyTables = $this->classToTableNames = array();
        foreach ($tables as $tableName => $table) {
            /* @var $table \Doctrine\DBAL\Schema\Table */
            if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
                $foreignKeys = $table->getForeignKeys();
            } else {
                $foreignKeys = array();
            }

            $allForeignKeyColumns = array();
            foreach ($foreignKeys as $foreignKey) {
                $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
            }

            $pkColumns=array();
            if ($table->hasPrimaryKey()) {
                $pkColumns = $table->getPrimaryKey()->getColumns();
                sort($pkColumns);
            }

            sort($allForeignKeyColumns);

            if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
                $this->manyToManyTables[$tableName] = $table;
            } else {
                // lower-casing is necessary because of Oracle Uppercase Tablenames,
                // assumption is lower-case + underscore separated.
                $className = $this->getClassNameForTable($tableName);
                $this->tables[$tableName] = $table;
                $this->classToTableNames[$className] = $tableName;
            }
        }
    }

在同一文件中查找loadMetadataForClass方法

  1. 。按照下面的说明修改代码。

查找下面陈述的代码:

代码语言:javascript
复制
try {
   $primaryKeyColumns = $this->tables[$tableName]->getPrimaryKey()->getColumns();
} catch(SchemaException $e) {
    $primaryKeyColumns = array();
}

如下所示修改:

代码语言:javascript
复制
try {
     $primaryKeyColumns = ($this->tables[$tableName]->hasPrimaryKey())?$this->tables[$tableName]->getPrimaryKey()->getColumns():array();
} catch(SchemaException $e) {
     $primaryKeyColumns = array();
}

即使对于没有主键的表,上面的解决方案也会创建映射(xml/yml/注解)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8429806

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档