2013-08-07 86 views
1

我有以下兩個表:與外鍵1-N的關係是不是主鍵(一次是AUTO_INCREMENT「ID」)與doctrine2/Symfony2的

CREATE TABLE IF NOT EXISTS `skills` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `skill_category` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `skill` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `icon_filename` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `display_priority` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `skill_category` (`skill_category`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `skills_categories` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `skill_category` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `display_priority` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `IDX_95FF1C8D47E90E27` (`skill_category`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

ALTER TABLE `skills` 
    ADD CONSTRAINT `skills_ibfk_1` FOREIGN KEY (`skill_category`) REFERENCES `skills_categories` (`skill_category`); 

注意兩者之間的外鍵關係skill_category列。

table structure

我試圖創建這些表之間的多對一/一對多關係。一個獨特的skill_category應該有很多技能。這種結構似乎做工精細,除了當我嘗試驗證映射我得到的錯誤:

The referenced column name 'skill_category' has to be a primary key column on the target entity class 'Resume\ResumeBundle\Entity\SkillsCategories'.

有由學說的要求所引用的列是主鍵。如果我把這個鍵作爲主鍵,我的id列不再自動增加,我想要的。所以mySQL似乎可以確定外鍵是主鍵,然而Doctrine抱怨這種情況。有人說,他們只是通過重新創建列固定它:

http://goo.gl/vvq0tu

我已經試過這一點,這似乎並沒有幫助我。所以要麼這是某種錯誤,要麼我對RDBMS有一個基本的誤解(完全有可能)。我的問題是我不應該使用'id'列嗎?如果我期望我的'skill_category'列是獨一無二的,那麼我應該把它作爲主鍵並刪除'id'列?這將解決我的問題,但將VARCHAR作爲主鍵會有什麼問題嗎?谷歌的答案似乎「不是真的」,但我希望從別人的角度來看。

回答

1

這就是究竟是我剛開始使用Doctrine時遇到過同樣的問題,是的,它來自對Doctrine如何將對象映射到關係數據庫的誤解。通過走出去的「關係」的世界中,和治療您的實體,如他們的對象

讓我們開始。在你的情況下,這裏有兩類對象:你有一個技能,並且你有一個類別。

那些在作怪僅有的兩個對象。沒有像SkillsCategories實體那樣的東西......它作爲一個對象是沒有意義的 - 這是一種關係。因此,給它一個ID並不意味着太多。

那麼這些兩個實體實際上是什麼樣子?

技能:

  • 一種ID
  • 甲名稱
  • 一個圖標文件名
  • 顯示優先級
  • 範疇實體它所屬

類別:

  • 的ID
  • 一個名稱
  • 屬於它

就是當你把這些實體在數據庫中,它看起來就像你會技能的實體的列表期望(除了我們沒有繪製屬於某個類別的技能列表 - 稍後將由Doctrine處理)。我建議您更新架構以反映這種變化:

CREATE TABLE IF NOT EXISTS `Skill` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `categoryId` int(11) NOT NULL, 
    `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `iconFilename` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `displayPriority` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `skill_category` (`categoryId`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `Category` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
    `displayPriority` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `IDX_95FF1C8D47E90E27` (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 

現在您可以定義通過主義的關係。以下是YAML可能的樣子:

Path\To\Entity\Skill: 
    type: entity 
    table: Skill 
    fields: 
     id: 
      id: true 
      type: integer 
      generator 
       strategy: AUTO 
     name: 
      type: string 
      length: 255 
     iconFilename: 
      type: string 
      length: 50 
     displayPriority: 
      type: integer 
    manyToOne: 
     category: 
      targetEntity: Category 
      inversedBy: skills 
      joinColumn: 
       name: categoryId 
       referencedColumnName: id 

Path\To\Entity\Category: 
    type: entity 
    table: Category 
    fields: 
     id: 
      id: true 
      type: integer 
      generator 
       strategy: AUTO 
     name: 
      type: string 
      length: 255 
     displayPriority: 
      type: integer 
    oneToMany: 
     skills: 
      targetEntity: Skill 
      mappedBy: category 

現在你有一個完全可行的模型!

一些例子...

說你想獲得一個技能的範疇的displayPriority:

$skill->getCategory()->getDisplayPriority(); 

...或者,如果你想獲得一個給定的類別下技能名稱的列表:

foreach ($category->getSkills() as $skill) { 
    echo $skill->getName(); 
} 

希望這有助於明確的東西一點點...

+0

感謝您的幫助,我實施了您的解決方案,但後來意識到您正在將'skillId'加入現有的'id'主鍵。我能做到這一點,但爲了便於數據插入(我與phpMyAdmin插入,我寧願不查找每個類別我想使用相應的ID,我寧願只直接使用的範疇,並沒有亂與IDS,如果我這樣做(加入通過類別和表不是IDS),那麼,我需要的類別是主鍵(教義要求),如果我這樣做,那麼IDS慣於增量,如果他們不是主鍵(MySQL的要求?) – Joe

+0

哎呦,是的......我的意思了'Skill' - >'category'加入列名是'categoryId',不'skillId'對此深感抱歉! –

+0

至於你的手動數據庫更新,你可以在phpMyAdmin中執行此操作:INSERT INTO Skill(name,iconFilename,displayPriority,categoryId)選擇「某個技能名稱」,「圖標文件」,5,id FROM Category WHERE name = 「某些類別名稱」?這使用'SELECT'的結果作爲你的'INSERT'的基礎。爲了簡化數據輸入,我只是不確定削弱模型是個好主意。 –

0

有做一個varchar主鍵沒有問題。如果您確實有空間或密鑰大小要求,則可以設置查找代碼表,但這會使數據庫和代碼比需要的更復雜。

我個人使用自動增量鍵僅用於輸入從過程我不用管:訂單,門票,活動等一般的東西都要從網絡過程跟蹤。

+0

是的,我想,如果我跟一個真正的RDBMS專家,他們會說'爲什麼你使用自動增量ID如果你正在創建獨特的類別 - 當類別提供這種獨特性時,不需要唯一的ID'。不過話又說回來,我剛剛得知更多關於代理v..s自然鍵,有的主張始終使用代理鍵: http://stackoverflow.com/questions/707657/picking-the-best-primary-key-numbering -system – Joe