教义多对多关系和onFlush事件

时间:2013-10-04 11:35:51

标签: sql doctrine-orm many-to-many entity-relationship entities

关于书籍和作者的小例子: 数据库结构:

enter image description here

实体(它们是使用symfony2控制台命令从数据库生成的):

作者:

    /**
 * Author
 *
 * @ORM\Table(name="authors")
 * @ORM\Entity
 */
class Author
{

    private $_isCachable = true;


    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Books", mappedBy="author", cascade={"persist","remove","detach","merge","refresh"})
     */
    private $book;

    /**
     * Constructor
     */
    public function __construct()
    {
    $this->book = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

图书:

 <?php

namespace App\CoreBundle\Entity;

use App\CoreBundle\RedisLayer\Marks\Insert;
use App\CoreBundle\RedisLayer\Marks\Update;
use Doctrine\ORM\Mapping as ORM;

/**
 * Book
 *
 * @ORM\Table(name="books")
 * @ORM\Entity
 */
class Book
{

    private $_isCachable = true;


    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="ttile", type="string", length=255, nullable=false)
     */
    private $ttile;

    /**
     * @var string
     *
     * @ORM\Column(name="isbn", type="string", length=255, nullable=false)
     */
    private $isbn;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="App\CoreBundle\Entity\Authors", inversedBy="book", cascade={"persist","remove","detach","merge","refresh"})
     * @ORM\JoinTable(name="author_books",
     *   joinColumns={
     *     @ORM\JoinColumn(name="book_id", referencedColumnName="id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     *   }
     * )
     */
    private $author;

    /**
     * Constructor
     */
    public function __construct()
    {
    $this->author = new \Doctrine\Common\Collections\ArrayCollection();
    }

}

所以当我运行这段代码时:

    $book = new \App\CoreBundle\Entity\Book();
    $book->setTtile('book title: '.uniqid());
    $book->setIsbn('book isbn: '.uniqid());

    $author = new \App\CoreBundle\Entity\Author();
    $author->setName('author title: '.uniqid());


    $author->addBook($book);

    $entityManager->persist($author);

    $entityManager->flush();

我希望doctrine能够生成这些SQL:

"START TRANSACTION"]

    # CREATE BOOK
    INSERT INTO books (ttile, isbn) VALUES (?, ?)
    array(2) {
      [1] =>
      string(25) "book title: 524ea3cf34d5f"
      [2] =>
      string(24) "book isbn: 524ea3cf34da3"
    }
    array(2) {
      [1] =>
      string(6) "string"
      [2] =>
      string(6) "string"
    }

    # CREATE AUTHOR
    INSERT INTO authors (name) VALUES (?)
    array(1) {
      [1] =>
      string(27) "author title: 524ea3cf34de9"
    }
    array(1) {
      [1] =>
      string(6) "string"
    }

    # CREATE LINKS
    INSERT INTO author_books (book_id, author_id) VALUES (?, ?)
    array(2) {
      [0] =>
      int(34)
      [1] =>
      int(23)
    }

"COMMIT"

但我只为#CERATE AUTHOR和#CREATE BOOK获得了SQL。没有生成用于链接表的SQL。

  1. 有什么问题?

  2. 如果我运行此代码:

    $book = new \App\CoreBundle\Entity\Book();
    $book->setTtile('book title: '.uniqid());
    $book->setIsbn('book isbn: '.uniqid());
    
    $author = new \App\CoreBundle\Entity\Author();
    $author->setName('author title: '.uniqid());
    
    $author->addBook($book);
    $book->addAuthor($author); // added
    
    $entityManager->persist($author);
    
    $entityManager->flush();
    
    一切都好。所以我需要为作者和作者添加书来预订吗?是否可以创建书籍和作者,然后预订作者和同花顺(不添加作者预订)?

  3. 如果我使用doctrine onFLush事件监听器,我可以使用getScheduledEntityUpdates(应更新的实体列表),getScheduledEntityInsertions(应更新的实体列表)和{{1} (unitOfWork对象的方法)(应删除的实体列表)方法。但这只是实体。如何获取有关链接表的信息?我需要在doctrine onFlush事件中获取用于链接表的SQL。

1 个答案:

答案 0 :(得分:1)

您需要确保Book:authors和Author:books在持久化之前都具有正确的值。

具体做法是:

class Authors
{
    public function addBook($book)
    {
        $this->books[] = $book;
        $book->addAuthor($this);
    }

在Book实体上执行相同操作。

BTW,将书籍和作者改为书籍和作者。否则它会让你发疯。如果需要,可以将表名保持为复数。

=============================================== =====

问题#3:

当doctrine创建链接表时,它会完全隐藏它。您需要做的是创建自己的BookAuthor实体,然后设置从它到Book / Author的一对多关系。此时您将拥有完全访问权限。如果需要,您还可以添加其他属性。