拥有side作为连接列的主键

Dav*_*idW 22 symfony doctrine-orm

注意: 主题冗长但详细,如果您使用Doctrine2和oneToOne关系,可能会派上用场.

最近我在学说中遇到了一个问题:

我使用oneToOne双向关系创建了User和UserData对象:

User:
...
  oneToOne:
    userdata:
      targetEntity: UserData
      mappedBy: user

UserData:
...
  oneToOne:
    user:
      targetEntity: User
      inversedBy: userdata
Run Code Online (Sandbox Code Playgroud)

所以UserData是拥有user_id列的拥有者:

user: id, ...
userdata: id, user_id, ...
Run Code Online (Sandbox Code Playgroud)

这就产生了一个问题,每次你获取一个User对象(单个用户,用户集合或其他对象的集合,用户加入它)时,Doctrine会为每个用户延迟加载一个UserObject.

问题描述如下:

这里描述的建议解决方案:

所以有三种方法:

  1. 等等,看看是否在Doctrine中解决了提议的解决方案,并在将来的版本中修复(可能不会发生)
  2. 手动将每个查询中的UserData加入User(仍然浪费资源,不需要UserData)
  3. 切换反面并使用户拥有自己的一面.

我决定和#3一起去.所以我的架构关系现在看起来像这样:

User:
...
  oneToOne:
    userdata:
      targetEntity: UserData
      inversedBy: user

UserData:
...
  oneToOne:
    user:
      targetEntity: User
      mappedBy: userdata
Run Code Online (Sandbox Code Playgroud)

这意味着我的表现在看起来像这样:

user: id, userdata_id, ...
userdata: id, ...
Run Code Online (Sandbox Code Playgroud)

我决定不再使用Userdata.id自动增量,而是手动设置它并将其与user.id匹配.这意味着UserData.id将始终匹配user.id.

问题我可以使用user.id(主要自动增量密钥)作为joinColum而不是userdata_id,因为它们总是具有相同的值吗?你认为这种做事有任何潜在的问题吗?

关于这个问题的任何其他提示或意见都非常受欢迎和赞赏.

Mic*_*ick 18

您还可以强制部分对象,以摆脱延迟加载:

use Doctrine\ORM\Query;

//...
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);
Run Code Online (Sandbox Code Playgroud)


Cha*_*yer 14

这是OneToOne关联的已知问题.关于这一点的github讨论值得一读.建议并拒绝解决方案(拉动请求).

建议

你的问题表明了Doctrine贡献者提出的相同解决方案:改变关系的拥有方.

其他选项已探索

我有一个名为实体类似的问题,Version即有一个OneToOne双向的关系Settings.每次我查询时Version(例如10个特定版本记录),Doctrine都会对连接进行额外的查询Settings(就好像它是Lazy Loading这些实体一样).这发生了,即使我没有Settings在任何地方引用,例如$Version->getSettings()->getSomeProperty().

手动加入

对我有用的唯一"解决方案"(hack)是Settings每次进行查询时手动为该实体包含JOIN Version.但由于我不需要额外的实体(在这种情况下),每次我以不同的方式查询此表时,这仍然是一个额外的不必要的查询.

特别懒

基于其他建议,我认为如果我明确地将这种关系指定为"额外的懒惰",那么它将起作用,例如

/**
 * @ManyToMany(targetEntity="Settings", mappedBy="version", fetch="EXTRA_LAZY")
 */
Run Code Online (Sandbox Code Playgroud)

但这不会影响水合作用.有关详细信息,请参阅Doctrine DocsEXTRA_LAZY.

水合类型:HYDRATE_ARRAY

在我的情况下(当我不需要实体时)帮助的是指定我想要作为数组(而不是对象)获取.

$query = $queryBuilder->getQuery();
$query->getResult(Query:HYDRATE_ARRAY);
Run Code Online (Sandbox Code Playgroud)

这将返回一个数组,因此它不会延迟加载OneToOne关联.但是,在我需要实体对象的其他环境中,我必须明确地加入实体(尽管不想要它).