我试图设置实体与原则,我坚持这个错误:当持久化数据时,我有一个SQL错误关于非空约束违反。实际上,Doctrine已经生成了一个没有外键值的插入语句。
An exception occurred while executing 'INSERT INTO user_access_company (end_at, created_at, updated_at, user_id, company_id) VALUES (?, ?, ?, ?, ?)' with params [null, "2022-12-12 23:06:57+0000", "2022-12-12 23:06:57+0000", null, 82]: SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "user_id" violates not-null constraint
这里是我的实体
class Participant implements ParticipantInterface
{
protected $id;
protected $source;
protected $identifier;
protected $firstName;
protected $lastName;
protected $emailAddress;
protected $createdAt;
protected $updatedAt;
}
class UserAccessCompany
{
private Participant $user;
private Company $company;
private ?DateTimeImmutable $endAt;
private DateTimeImmutable $createdAt;
private DateTimeImmutable $updatedAt;
}
和相关的XML映射
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
>
<entity name="Participant" table="message_participant">
<id name="id" type="bigint">
<generator strategy="AUTO" />
</id>
<field name="source" type="string" />
<field name="identifier" type="integer" />
<field name="firstName" type="string" />
<field name="lastName" type="string" nullable="true"/>
<field name="emailAddress" type="string" nullable="true">
<field name="createdAt" type="datetime"><gedmo:timestampable on="create"/></field>
<field name="updatedAt" type="datetime"><gedmo:timestampable on="update"/></field>
</entity>
</doctrine-mapping>
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="UserAccessCompany" table="user_access_company">
<id name="user" association-key="true"/>
<id name="company" association-key="true"/>
<field name="endAt" type="datetimetz_immutable" column="end_at" nullable="true"/>
<field name="createdAt" type="datetimetz_immutable" column="created_at"><gedmo:timestampable on="create"/></field>
<field name="updatedAt" type="datetimetz_immutable" column="updated_at"><gedmo:timestampable on="create"/></field>
<many-to-one field="user" target-entity="Participant">
<join-columns>
<join-column name="user_id" referenced-column-name="identifier"/>
</join-columns>
</many-to-one>
<many-to-one field="company" target-entity="Company">
<join-columns>
<join-column name="company_id"/>
</join-columns>
</many-to-one>
</entity>
</doctrine-mapping>
我使用像这样的简单代码来插入数据:
$userAccessCompany = new UserAccessCompany($user, $company, $endAt);
$this->getEntityManager()->persist($userAccessCompany);
$this->getEntityManager()->flush();
$user
和$company
是已经保存在数据库中的实体,如果我转储$user->identifier
,我在里面有一个值。然而,生成的SQL语句是这样的:INSERT INTO user_access_company (end_at, created_at, updated_at, user_id, company_id) VALUES (null, "2022-12-12 23:06:57+0000", "2022-12-12 23:06:57+0000", null, 82)
,因此user_id
值缺失
公司实体以类似的方式声明(不指定inversedBy/mappedBy),当我生成迁移时,在userAccessCompany.user_id
引用participant.identifier
之间有一个外键,所以doctrine似乎意识到了这个关系
一些额外的注意事项,我已经简化了实体,使它们在这里可读,我在所有实体中定义了getter和setter。我还尝试使用注释映射,没有运气,并在userAccessCompany中添加id字段,删除了user/company
上的主键。作为参考,我使用Symfony 4.4和doctrine/orm 2.7.3
这是理论的一个已知限制,我在文档中遗漏了这一点。
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/limitations-and-known-issues.html join-columns-with-non-primary-keys
非主键连接列
不能使用连接列指向非主键。Doctrine将认为这些是主键,并使用数据创建延迟加载代理,这可能导致意想不到的结果。出于性能原因,Doctrine可以在运行时不验证此设置的正确性,而只能通过validate Schema命令验证。