3

OneToMany 関係に問題があります。私は現在、元のログ行と、キーワードを含む行からの解析されたメッセージを格納するログ アナライザーに取り組んでいます。データベース構造は次のようになります。

データベース

CREATE TABLE IF NOT EXISTS `keywords` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `row_id` bigint(20) unsigned NOT NULL,
  `type` varchar(50) NOT NULL,
  `value` varchar(128) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `type` (`type`),
  KEY `value` (`value`),
  KEY `FK_keywords_rows` (`row_id`),
  CONSTRAINT `FK_keywords_rows` FOREIGN KEY (`row_id`) REFERENCES `rows` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `messages` (
  `row_id` bigint(20) unsigned NOT NULL,
  `profile_name` varchar(50) NOT NULL,
  `type` varchar(50) NOT NULL,
  `subtype` varchar(50) NOT NULL,
  `time` datetime NOT NULL,
  KEY `FK_messages_rows` (`row_id`),
  KEY `FK_messages_profiles` (`profile_name`),
  CONSTRAINT `FK_messages_profiles` FOREIGN KEY (`profile_name`) REFERENCES `profiles` (`name`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_messages_rows` FOREIGN KEY (`row_id`) REFERENCES `rows` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `profiles` (
  `name` varchar(50) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `rows` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `profile_name` varchar(50) NOT NULL,
  `content` varchar(1024) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_rows_profiles` (`profile_name`),
  CONSTRAINT `FK_rows_profiles` FOREIGN KEY (`profile_name`) REFERENCES `profiles` (`name`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

http://yuml.me/3e8a2413.png

ログ アナライザーは、正しく解析されていないメッセージをキーワードから削除できますが、行は再解析のために残ります。これが、メッセージがメッセージの row_id を参照する独自の主キーとキーワードを持たない理由です。私のエンティティは次のようになります。

プロフィール

/**
 * Class Profile
 * @package Ghopple\Entity
 * @ORM\Entity
 * @ORM\Table(name="profiles")
 */
class Profile
{

    /**
     * @ORM\Id
     * @ORM\Column(name="name", type="string", length=50)
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(name="description", type="string", length=255)
     * @var string
     */
    protected $description;

    /**
     * @ORM\OneToMany(targetEntity="Row", mappedBy="profile", fetch="LAZY")
     * @var Row[]
     */
    protected $rows;

    /**
     * @ORM\OneToMany(targetEntity="Message", mappedBy="profile", fetch="LAZY")
     * @var Message[]
     */
    protected $messages;

/**
 * Class Row
 * @package Ghopple\Entity
 * @ORM\Entity
 * @ORM\Table(name="rows")
 */
class Row
{

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

    /**
     * @ORM\ManyToOne(targetEntity="Profile", inversedBy="rows")
     * @ORM\JoinColumn(name="profile_name", referencedColumnName="name")
     * @var Profile
     */
    protected $profile;

    /**
     * @ORM\Column(name="content", type="string", length=1024)
     * @var string
     */
    protected $content;

    /**
     * @ORM\OneToOne(targetEntity="Message", mappedBy="row")
     * @var Message
     */
    protected $message;

メッセージ

/**
 * Class Message
 * @package Ghopple\Entity
 * @ORM\Entity
 * @ORM\Table(name="messages")
 */
class Message
{

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

    /**
     * @ORM\Column(name="type", type="string", length=50)
     * @var string
     */
    protected $type;

    /**
     * @ORM\Column(name="subtype", type="string", length=50)
     * @var string
     */
    protected $subtype;

    /**
     * @ORM\ManyToOne(targetEntity="Profile", fetch="EAGER")
     * @ORM\JoinColumn(name="profile_name", referencedColumnName="name")
     * @var Profile
     */
    protected $profile;

    /**
     * @ORM\OneToOne(targetEntity="Row", fetch="LAZY", cascade={"persist"})
     * @ORM\JoinColumn(name="row_id", referencedColumnName="id")
     * @var Row
     */
    protected $row;

    /**
     * @ORM\OneToMany(targetEntity="Keyword", mappedBy="message", cascade={"persist"})
     * @var Keyword[]
     */
    protected $keywords;

    /**
     * @ORM\Column(name="time", type="datetime")
     * @var DateTime
     */
    protected $time;

キーワード

/**
 * Class Keyword
 * @package Ghopple\Entity
 * @ORM\Entity
 * @ORM\Table(name="keywords")
 */
class Keyword
{

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

    /**
     * @ORM\Column(name="type", type="string", length=50)
     * @var string
     */
    protected $type;

    /**
     * @ORM\ManyToOne(targetEntity="Message", inversedBy="keywords")
     * @ORM\JoinColumn(name="row_id", referencedColumnName="row_id")
     * @var Message
     */
    protected $message;

    /**
     * @ORM\Column(name="value", type="string", length=128)
     * @var string
     */
    protected $value;

そして、それが私がやろうとしていることです:

    ....
    $profile = $profileRepository->findOneBy(array('name' => 'ghostpp-01'), array('name' => 'DESC'));

    $row = new Row();
    $row->setContent('content');
    $row->setProfile($profile);

    $message = new Message();
    $message->setType('type');
    $message->setSubtype('subtype');
    $message->setTime(new DateTime());
    $message->setProfile($profile);
    $message->setRow($row);

    $keyword = new Keyword();
    $keyword->setType('keyword');
    $keyword->setValue('value');

    $message->addKeyword($keyword);

    $entityManager->persist($message);
    $entityManager->flush();
    ....

キーワード挿入ステートメントで例外メッセージが表示されました。

An exception occurred while executing 'INSERT INTO keywords (type, value, row_id) VALUES (?, ?, ?)' with params ["keyword", "value", null]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'row_id' cannot be null

ここやインターネットで多くのエントリを読んだので、メッセージにキーワードを追加する際に次の行を追加しました。

    /**
     * @param Keyword $keyword
     * @return $this
     */
    public function addKeyword(Keyword $keyword)
    {
        if (!$this->keywords->contains($keyword)) {
            $this->keywords->add($keyword);
            $keyword->setMessage($this);
        }
        return $this;
    }

    /**
     * @param Keyword $keyword
     * @return $this
     */
    public function removeKeyword(Keyword $keyword)
    {
        if ($this->keywords->contains($keyword)) {
            $this->keywords->remove($keyword);
            $keyword->unsetMessage();
        }
        return $this;
    }

http://www.doctrine-project.org/jira/browse/DDC-2244からこれを取得しており、解決すべき同じ問題について説明しています。関連付けをメッセージとキーワードに設定しましたが、エラーを解決する必要がありますが、解決しませんでした。今、私はアイデアがありません....

編集:

ログでわかるように、彼は正しい順序で行を作成しますが、挿入後に row_id を解決できません。

SELECT t0.name AS name1, t0.description AS description2 FROM profiles t0 WHERE t0.name = ? ORDER BY t0.name DESC LIMIT 1
Params     0 => string(10) "ghostpp-01" 
Types     0 => string(6) "string" 
Time0.011378049850464

"START TRANSACTION"
Params
Types
Time0.00012993812561035

INSERT INTO rows (content, profile_name) VALUES (?, ?)
Params     1 => string(7) "content" 
    2 => string(10) "ghostpp-01" 
Types     1 => string(6) "string" 
    2 => string(6) "string" 
Time0.012298107147217

INSERT INTO messages (type, subtype, time, profile_name, row_id) VALUES (?, ?, ?, ?, ?)
Params     1 => string(4) "type" 
    2 => string(7) "subtype" 
    3 => object(stdClass)#511 (3) { ["__CLASS__"]=> string(8) "DateTime" ["date"]=> string(25) "2013-10-09T06:36:29+02:00" ["timezone"]=> string(12) "Europe/Paris" } 
    4 => string(10) "ghostpp-01" 
    5 => int(30) 
Types     1 => string(6) "string" 
    2 => string(6) "string" 
    3 => string(8) "datetime" 
    4 => string(6) "string" 
    5 => string(7) "integer" 
Time0.00024700164794922

INSERT INTO keywords (type, value, row_id) VALUES (?, ?, ?)
Params     1 => string(7) "keyword" 
    2 => string(5) "value" 
    3 => NULL 
Types     1 => string(6) "string" 
    2 => string(6) "string" 
    3 => NULL 
Time0
SQL "ROLLBACK"
4

0 に答える 0