2013-08-07 7 views
1

나는 다음과 같은 두 개의 테이블이 있습니다1-N의 관계는 doctrine2/symfony2와 (주는 AUTO_INCREMENT 'ID를'입니다)

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

나는 이러한 테이블 사이 manytoone/onetomany 관계를 만들려고하고 있습니다. 고유 한 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은 외래 키가 기본 키라는 사실로 괜찮은 것 같습니다. 그러나 교리는이 경우에 대해 불평합니다. 누군가 그들은 단지 열을 다시하여 고정 말했다 : 나는이 시도했습니다, 그리고 나를 위해 도움을 보이지 않았다

http://goo.gl/vvq0tu

. 그래서 이것은 어떤 종류의 버그이거나 RDBMS에 대한 근본적인 오해가 있습니다 (완전히 가능함). 내 문제는 내가 'ID'열을 전혀 사용하지 않아야한다는 것입니까? 만약 내가 'skill_category'컬럼이 고유해야만 기본 키를 만들고 'id'컬럼을 제거해야한다고 생각한다면? 그게 내 문제를 해결할 수 있지만 기본 키를 VARCHAR 만들기에 어떤 문제가 있습니까? Google의 대답은 '별로'아닌 것 같지만 다른 사람의 견해에 감사드립니다.

답변

1

정확히 처음 교리를 사용하기 시작했을 때 내가 가진 그래, 그것은 관계형 데이터베이스에 어떻게 교리 맵 오브젝트에 대해 약간의 오해에서 비롯 같은 문제를 해결합니다.

"관계형"세계에서 벗어나 자신의 개체를 자신의 개체처럼 다루어 보겠습니다. 당신의 경우에는 여기에 두 가지 종류의 대상이 있습니다 : 당신은 기술이 있고 당신은 범주가 있습니다.

이 두 개만 재생할 수 있습니다. SkillsCategories 엔티티와 같은 것은 존재하지 않습니다 ... 그것은 객체로서 이해가되지 않습니다 - 그것은 관계입니다. 그리고 그런 식으로 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 

이제 완전히 작동하는 모델이 있습니다. 주어진 범주 아래 스킬 이름의 목록을 원한다면

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

... 나 :

몇 가지 예 ...

당신이 스킬의 종류의 displayPriority을 얻고 싶었다 말 :

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

희망이 명확한 것까지 도움 좀 ...

+0

도움을 주셔서 감사합니다. 귀하의 솔루션을 구현했지만 기존 'id'기본 키에 'skillId'를 추가한다는 것을 깨달았습니다. 필자는이 작업을 수행 할 수 있지만 데이터 삽입을 용이하게하기 위해 (필자는 phpmyadmin을 사용하여 삽입하고 싶습니다. 사용하려는 각 카테고리의 해당 ID를 조회하지 않고 차라리 카테고리를 직접 사용하고 엉망으로 만들 필요가 없습니다. ID를 사용하여 테이블을 조인 할 경우 기본 키 (교리 요구 사항) 카테고리가 필요합니다. 그렇게하면 ID가 증가하지 않습니다. 기본 키 (mysql 요구?) – Joe

+0

아, 그래 ... 나는 '스킬'->'카테고리'조인 컬럼 이름이'skillId'가 아닌'categoryId'이어야한다는 의미였습니다. –

+0

수동 데이터베이스 업데이트는 phpMyAdmin에서 할 수 있습니다. INSERT INTO 스킬 (name, iconFilename, displayPriority, categoryId) SELECT "스킬 이름", "아이콘 파일", 5, id FROM 카테고리 선택 WHERE name = "일부 카테고리 이름"? 이것은'INSERT'의 기초로서'SELECT'의 결과를 사용합니다. 데이터 입력을 쉽게하기 위해 모델을 약화시키는 것이 좋은 생각인지 모르겠습니다. –

0

varchar를 기본 키로 만드는 데 아무런 문제가 없습니다. 공간 또는 키 크기 요구 사항이 실제로있는 경우 조회 코드 테이블을 설정할 수는 있지만 데이터베이스 및 코드가 필요 이상으로 복잡해집니다.

개인적으로 제어 할 수없는 프로세스 (주문, 티켓, 이벤트 등)의 입력에 대해서만 자동 증가 키를 사용합니다. 일반적으로 웹 프로세스에서 추적하고 있습니다.

+0

내가 얘기하면 그래, 나는 생각하고 진정한 전문가 인 RDBMS에서는 '고유 한 카테고리를 만드는 경우 자동 증가 ID를 사용하는 이유는 무엇입니까? 카테고리가이 고유성을 제공 할 때 고유 ID가 필요하지 않습니다.'라고 말할 것입니다. 그런데 다시 한 번 대리 변수 v ... 자연 키에 대해 더 배웠고 대리 키를 항상 대리 키를 사용하는 일부 옹호자 : http://stackoverflow.com/questions/707657/picking-the-best-primary-key-numbering -system – Joe