在重新构建web应用程序时,我正在使用遗留数据库。我想使用Symfony2.x,它显然具有Doctrine作为ORM。
我有大约50个没有主键的(mysql)表。当我尝试生成模型时,它不允许我这样做,并抛出一个异常"No Primary Key on ... table“。
我必须在表上有主键才能使用Doctrine吗?或者有什么方法可以绕过它吗?
任何帮助都是最好的。
谢谢。
发布于 2011-12-08 20:01:21
原理要求每个实体类都有一个标识符/主键。
看看这个页面:http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#identifiers-primary-keys
发布于 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)
原始代码是:
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;
}
}
}修改后的代码为:
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方法
查找下面陈述的代码:
try {
$primaryKeyColumns = $this->tables[$tableName]->getPrimaryKey()->getColumns();
} catch(SchemaException $e) {
$primaryKeyColumns = array();
}如下所示修改:
try {
$primaryKeyColumns = ($this->tables[$tableName]->hasPrimaryKey())?$this->tables[$tableName]->getPrimaryKey()->getColumns():array();
} catch(SchemaException $e) {
$primaryKeyColumns = array();
}即使对于没有主键的表,上面的解决方案也会创建映射(xml/yml/注解)。
https://stackoverflow.com/questions/8429806
复制相似问题