2011-10-10 55 views
36

我很難理解級聯操作的學說手冊explanation,需要有人幫助我理解簡單的ManyToOne關係中的選項。OneToMany的學說級聯選項

在我的應用程序中,我有一個名爲Article的表/實體,它有一個外鍵字段引用名爲Topic的表/實體中的「id」字段。

當我創建新文章時,我從下拉菜單中選擇主題。這會在文章表中的「topic_id」外鍵字段中插入一個整數。

我有$主題關聯的實體條這樣設置:

/** 
* @ManyToOne(targetEntity="Topic") 
* @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false) 
*/ 
private $topic; 

的主題實體沒有關於文章實體的任何往復註解。主題不關心什麼文章引用它們,並且當引用該主題的文章被刪除時什麼都不需要發生。

因爲我沒有在Article實體中指定級聯操作,所以當我嘗試創建新的Article時,Doctrine拋出一個錯誤:「通過未配置爲級聯持久操作的關係找到新實體。堅持新的實體或配置級聯堅持操作的關係。「

所以我知道我需要選擇級聯操作才能包含在Article實體中,但是如何知道在這種情況下選擇哪種操作?

從閱讀Doctrine手冊,「分離」聽起來像是正確的選擇。但研究別人的類似問題herehere讓我覺得我想用「堅持」來代替。

任何人都可以幫助我理解什麼「堅持」,「刪除」,「合併」和「分離」意味着就像我所描述的一個簡單的ManyToOne關係?

+6

+1爲好問題。希望有人會盡快回答,我想了解更多關於級聯選項。目前缺乏關於Doctrine2的書籍或文檔。 – gremo

回答

27

在Doctrine2文檔「9.6. Transitive persistence/Cascade Operations」中,有幾個應該如何配置實體的示例,以便在持久化$ article時,$ topic也將被持久化。在你的情況我建議這個註解爲主題的實體:

/** 
* @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"}) 
*/ 
private $articles; 

這種解決方案的缺點是,你必須包括$物品收集主題的實體,但你可以離開它沒有私人的getter/setter方法。

正如@庫爾特 - krueckeberg提到,必須創建新文章的時候,即:

$topic = $em->getRepository('Entity\Topic')->find($id); 
$article = new Article($topic); 
$em->persist($article); 
$em->flush(); 

// perhaps, in this case you don't even need to configure cascade operations 

好運氣傳給真正的主題實體!

+0

鏈接已死亡。你能找到一個新的嗎? – ferdynator

+0

@ferdynator我已更新鏈接,感謝您的通知。 – Serg

0

如果您有一條@OneToMany單向關聯,就像Doctrine Reference的6.10節中所描述的那樣,那麼很可能您在調用flush之前忘記了保留主題。不要在Article中設置topic_id主鍵。而是設置Topic實例。

例如,假定條和主題實體像這樣:

<?php 
namespace Entities; 

/** 
@Entity 
@Table(name="articles") 
*/ 
class Article { 

/** 
* @Id 
* @Column(type="integer", name="article_id") 
* @GeneratedValue 
*/ 
    protected $id; 

/** 
* @Column(type="text") 
*/ 
protected $text; 

/** 
* @ManyToOne(targetEntity="Topic", inversedBy="articles") 
* @JoinColumn(name="topic_id", referencedColumnName="topic_id") 
*/ 
protected $topic; 

public function __construct($text=null) 
{ 
    if (!is_null($text)) { 
     $this->text = $text; 
    } 
} 
public function setArticle($text) 
{ 
    $this->text = $text; 
} 

public function setTopic(Topic $t) 
{ 
    $this->topic = $t; 
} 
} 

<?php 
namespace Entities; 
/** 
    @Entity 
    @Table(name="topics") 
*/ 
class Topic { 

/** 
* @Id 
* @Column(type="integer", name="topic_id") 
* @GeneratedValue 
*/ 
    protected $id; 

    public function __construct() {} 

    public function getId() {return $this->id;} 
} 

後生成模式:

# doctrine orm:schema-tool:create 

你的代碼保存這些實體看起來象是這樣

//configuration omitted.. 
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config); 

$topic = new Entities\Topic(); 
$article1 = new Entities\Article("article 1"); 
$article2 = new Entities\Article("article 2"); 
$article1->setTopic($topic); 
$article2->setTopic($topic); 
$em->persist($article1); 
$em->persist($article2); 
$em->persist($topic); 

try { 
    $em->flush(); 
} catch(Exception $e) { 
    $msg= $e->getMessage(); 
    echo $msg . "<br />\n"; 
} 
return; 

我希望這有助於。