原则 2:ORM,刷新后外键为零
我正在使用 Doctrine 2 ORM,但遇到了这个问题。
我有三个实体:地址、位置和组织单位。
他们之间的关系是: 地址(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;
}
,我真的不知道它出了什么问题,这个问题不仅发生在这里,而且当我有多对多关系并且我将两侧插入一次时也会发生。
编辑: 而且我还注意到,当我坚持并仅刷新地址和位置,并在刷新后对它们进行 vardump 时,只有位置具有 ID 并且地址为零(在刷新之前它为 NULL)。
I'm using Doctrine 2 ORM and I have this problem.
I have three Entities, Address, Location and OrganizationalUnit.
Relations between them are:
Address (OneToOne) Location,
OrganizationalUnit (ManyToOne) Address.
Problem:
When I'm trying to persist all objects (code below), it sets OrganizationalUnit(FK:Address) to zero instead of Address(ID).
When I'm selecting(find) or updating something it all works well.
Code:
Here is the code that makes the persists.
//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();
This code generates SQL like this (I have it from MySQL Server Log)
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
Which is wrong because of "('novytest', 7, 0, NULL)" this zero (database model below)
Database look like this:
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;
My ORM Models look like this
For Location:
/**
* @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;
}
For 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;
}
And for OrganizationalUnit
/**
* @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;
}
I really don't know what's wrong with it, this problem not occur only here but also when I have ManyToMany relation and I'm inserting both sides in one flush.
Edit:
And also I notice when I persist and flush only address and location, and vardump them after flush, only location have ID and address's is zero (before flush it's NULL).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这不起作用,因为您已声明两次地址和组织之间的关系。
将组织结构更改为:
编辑
查看您的位置模型并发现这一行:
您将您的位置引用到自动增量的主键。难道和这个有关系吗?您可能需要将 location_id 列添加到地址表中。现在,您为 id 列分配了两次值。
诗。看起来还有更多事情无法正常工作,因此必须尝试一次解决一个。
This is not working because you have the relation between Address and Organisation declared twice.
Change organisational to something like:
EDIT
Looked at your location model and found this line:
You reference your location to your primary key which autoincrements. Can it have something to do with this? You probably need to add a location_id column to your address table. Now you assign a value twice to your id column.
Ps. it looks like there are more things not working correctly, so must try to solve the one at a time.