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;
ログ アナライザーは、正しく解析されていないメッセージをキーワードから削除できますが、行は再解析のために残ります。これが、メッセージがメッセージの 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"