【问题标题】:Doctrine 2: ORM, zero foreign key after flush原则 2:ORM,刷新后外键为零
【发布时间】:2011-09-03 08:58:52
【问题描述】:

我正在使用 Doctrine 2 ORM,我遇到了这个问题。

我有三个实体,AddressLocationOrganizationalUnit

它们之间的关系是: 地址 (OneToOne) 位置, 组织单位 (ManyToOne) 地址。

问题: 当我尝试持久化所有对象(下面的代码)时,它将 OrganizationalUnit(FK:Address) 设置为零而不是 Address(ID)。

当我选择(查找)或更新某些内容时,一切正常。

代码:

这是使持久化的代码。

//Entity manager
$em = Zend_Registry::get('em');

$location = new Application_Model_Location();
$location->setLatitude(0);
$location->setLongitude(0);

$address = new Application_Model_Address();
$address->setCity('test');
$address->setCountry('cz');
$address->setNumber(123456);
$address->setPostalCode(123456);
$address->setStreet('street');

$address->setLocation($location);
$location->setAddress($address);

$organization = new Application_Model_Organizationalunit();
$organization->setName('novytest');
$organization->setType($organizationType[0]);

$address->addOrganization($organization);
$organization->setAddress($address);

$em->persist($location);
$em->persist($address);
$em->persist($organization);

$em->flush();

这段代码生成这样的 SQL(我从 MySQL 服务器日志中得到它)

START TRANSACTION
INSERT INTO Location (longitude, latitude, cartographicSquare, id) VALUES ('0', '0', NULL, NULL)
INSERT INTO Address (street, number, city, postalCode, country, id) VALUES ('ulice', '123456', 'test', '123456', 'cz', 11)
INSERT INTO OrganizationalUnit (name, type, address, parentId) VALUES ('novytest', 7, 0, NULL)
ROLLBACK

哪个是错的,因为“('novytest', 7, 0, NULL)”这个零(数据库模型如下)

数据库如下所示:

CREATE TABLE  `rotifera`.`location` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `longitude` double NOT NULL,
  `latitude` double NOT NULL,
  `cartographicSquare` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE  `rotifera`.`address` (
  `id` int(11) NOT NULL DEFAULT '0',
  `street` varchar(100) NOT NULL,
  `number` varchar(20) NOT NULL,
  `city` varchar(100) NOT NULL,
  `postalCode` varchar(10) NOT NULL,
  `country` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_Address_Location` (`id`),
  CONSTRAINT `fk_Address_Location` FOREIGN KEY (`id`) REFERENCES `location` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE  `rotifera`.`organizationalunit` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `type` int(11) NOT NULL,
  `address` int(11) DEFAULT NULL,
  `parentId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_OrganizationalUnit_Address1` (`address`),
  KEY `fk_OrganizationalUnit_OrganizationalUnitType1` (`type`),
  KEY `fk_OrganizationalUnit_OrganizationalUnit1` (`parentId`),
  CONSTRAINT `fk_OrganizationalUnit_Address1` FOREIGN KEY (`address`) REFERENCES `address` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_OrganizationalUnit_OrganizationalUnit1` FOREIGN KEY (`parentId`) REFERENCES `organizationalunit` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_OrganizationalUnit_OrganizationalUnitType1` FOREIGN KEY (`type`) REFERENCES `organizationalunittype` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我的 ORM 模型如下所示

位置:

/**
 * @Entity
 * @table(name="Location")
 */
class Application_Model_Location {

    /**
     * @id @column(type="integer")
     * @generatedValue
     */
    private $id;
    /** @column(type="float") */
    private $longitude;
    /** @column(type="float") */
    private $latitude;
    /** @column(type="integer", nullable=true) */
    private $cartographicSquare;
    /**
    * @OneToOne(targetEntity="Application_Model_Address", mappedBy="location")
    */
    private $address;

public function setId($id) {
    $this->id = $id;
}

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

public function getLongitude() {
    return $this->longitude;
}

public function setLongitude($longitude) {
    $this->longitude = $longitude;
}

public function getLatitude() {
    return $this->latitude;
}

public function setLatitude($latitude) {
    $this->latitude = $latitude;
}

public function getCartographicSquare() {
    return $this->cartographicSquare;
}

public function setCartographicSquare($cartographicSquare) {
    $this->cartographicSquare = $cartographicSquare;
}

public function getAddress() {
    return $this->address;
}

public function setAddress($address) {
    $this->address = $address;
}

地址:

/**
 * @Entity
 * @table(name="Address")
 */
class Application_Model_Address {

    /**
     * @id 
     * @column(type="integer")
     * @generatedValue
     */
    private $id;
    /** @column(length=100) */
    private $street;
    /** @column(length=100) */
    private $number;
    /** @column(length=100) */
    private $city;
    /** @column(length=100) */
    private $postalCode;
    /** @column(length=100) */
    private $country;
    /**
    * @OneToOne(targetEntity="Application_Model_Location", inversedBy="address")
    * @JoinColumn(name="id", referencedColumnName="id")
    */
    private $location;
    /**
    * @OneToMany(targetEntity="Application_Model_Organizationalunit", mappedBy="address")
    */
    private $organization;

public function setId($id) {
    $this->id = $id;
}

public function getId() {
    return ($this->id > 0) ? $this->id : $this->location->getId();
}

public function getStreet() {
    return $this->street;
}

public function setStreet($street) {
    $this->street = $street;
}

public function getNumber() {
    return $this->number;
}

public function setNumber($number) {
    $this->number = $number;
}

public function getCity() {
    return $this->city;
}

public function setCity($city) {
    $this->city = $city;
}

public function getPostalCode() {
    return $this->postalCode;
}

public function setPostalCode($postalCode) {
    $this->postalCode = $postalCode;
}

public function getCountry() {
    return $this->country;
}

public function setCountry($country) {
    $this->country = $country;
}

public function getLocation() {
    return $this->location;
}

public function setLocation($location) {
    $this->location = $location;
}

public function getOrganization() {
    return $this->organization;
}

public function addOrganization($organization) {
    $this->organization->add($organization);
}

public function __construct() {
    $this->organization = new \Doctrine\Common\Collections\ArrayCollection;
}

对于组织单位

/**
 * @Entity
 * @table(name="OrganizationalUnit")
 */
class Application_Model_Organizationalunit {

    /**
     * @id 
     * @column(type="integer")
     * @generatedValue
     */
    private $id;
    /** @column(length=100) */
    private $name;
    /**
     * @ManyToOne(targetEntity="Application_Model_Organizationalunittype",
     *   inversedBy="id")
     * @JoinColumn(name="type",
     *   referencedColumnName="id")
     */
     private $type;
     /**
      * @ManyToOne(targetEntity="Application_Model_Address", inversedBy="organization")
      * @JoinColumn(name="address", referencedColumnName="id")
      */
    private $address;
    /**
     * @OneToOne(targetEntity="Application_Model_Organizationalunit")
     * @JoinColumn(name="parentId",
     *  referencedColumnName="id")
     */
    private $parentId;

public function setId($id) {
    $this->id = $id;
}

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

public function getName() {
    return $this->name;
}

public function setName($name) {
    $this->name = $name;
}

public function getType() {
    return $this->type;
}

public function setType($type) {
    $this->type = $type;
}

public function getAddress() {
    return $this->address;
}

public function setAddress($address) {
    $this->address = $address;
}

public function getParentId() {
    return $this->parentId;
}

public function setParentId($parentId) {
    $this->parentId = $parentId;
}

我真的不知道它有什么问题,这个问题不仅发生在这里,而且当我有 ManyToMany 关系并且我将两边都插入一个冲洗时。

编辑: 而且我还注意到,当我坚持并仅刷新地址和位置,并在刷新后对它们进行 vardump 时,只有位置的 ID 和地址为零(在刷新之前它为 NULL)。

【问题讨论】:

  • 你能显示$address->addOrganization($organization);方法和$organization->setAddress($address);方法的代码吗?看起来这些方法有问题。
  • 刚刚添加。感谢您的宝贵时间。

标签: php orm doctrine foreign-keys


【解决方案1】:

这不起作用,因为您有两次声明地址和组织之间的关系。

将组织更改为:

/**
 * @Entity
 * @table(name="OrganizationalUnit")
 */
class Application_Model_Organizationalunit {

    ...

    /**
     * @ManyToOne(targetEntity="Application_Model_Address", inversedBy="organisation")
     * @JoinColumn(name="address", referencedColumnName="id")
     */
    private $address;

    ...
}

/**
 * @Entity
 * @table(name="Address")
 */
class Application_Model_Address {

    ...

    /**
     * @OneToMany(targetEntity="Application_Model_Organizationalunit", mappedBy="address")
     */
    private $organization;
}

编辑 查看了您的位置模型,发现了这一行:

/**
 * @OneToOne(targetEntity="Application_Model_Location", inversedBy="address")
 * @JoinColumn(name="id", referencedColumnName="id")
 */
private $location;

您将您的位置引用到自动递增的主键。这可能与此有关吗?您可能需要在地址表中添加 location_id 列。现在,您为 id 列分配了两次值。

附言。看起来还有很多事情不能正常工作,所以必须尝试一次解决一个。

【讨论】:

  • 我已根据您的帖子进行了编辑(也在我的问题中对其进行了编辑),但我仍然收到相同的错误(外键仍然为零)。而且我还注意到,当我坚持并仅刷新地址和位置,并在刷新后对它们进行 vardump 时,只有位置的 ID 和地址为零(在刷新之前它为 NULL)。
  • 编辑:我在地址构造函数中有 ArrayCollection。对不起,我编辑并添加了模型的整个代码,并且有构造。模型也没有父类,因此不需要parent::__construct();。顺便说一句,我感谢您的耐心,并感谢您的宝贵时间。
  • Edit2:你是对的。问题是地址中主键的引用位置。这是教义 2.0 中的一个问题,2.1 应该解决这个问题。所以我编辑地址表以获得 location_id 键。谢谢。
猜你喜欢
  • 2014-12-15
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 2016-07-14
相关资源
最近更新 更多