在这一点上,我不确定问题是与学说还是与symfony有关。
我有一个名为Field的实体。它有一个属性dataTable,使用通常的getter和setter方法。在我的一个支持类中,我使用setter方法将dataTable更改为临时值。我永远不会在这个类或调用它的控制器中调用。但是,我发现数据库正在使用此临时值进行更新。
如果需要,我可以添加一个虚拟属性并使用它,但我认为如果我能避免这种情况,代码会更清晰。我怎样才能确保该学说只能保留我明确告诉它的内容?
实体映射:
type: entity
gedmo:
soft_deleteable:
field_name: deletedAt
time_aware: false
id:
id:
type: integer
generator:
strategy: auto
fields:
name:
type: string
sortorder:
type: integer
dataTable:
type: string
type:
type: string
columnAdded:
type: boolean
deletedAt:
type: date
nullable: true
manyToOne:
section:
targetEntity: Domain\Model\Section
inversedBy: fields
oneToMany:
fieldOptions:
targetEntity: FieldOption
mappedBy: field
oneToOne:
zmrList:
targetEntity: Domain\Model\ZmrList
相关的控制器代码:(在控制器中永远不会调用Persist)
$columns = $this->queryBuilder->getListColumns($list);
$filters = $this->queryBuilder->composeListFilters($list);
$query = $this->queryBuilder->build($columns, $filters, $list->getForm()->getId(), $instanceId);
QueryBuilder中的相关代码:
foreach ($details['columns'] as $k=>$layerColumn) {
$this->columns[$layerColumn]->getField()->setDataTable('table_'.$alias);
}
二传函数:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
免责声明:以下内容适用于默认更改跟踪策略(隐式)
根据定义,flush
将对托管实体所做的任何更改写入数据库。
坚持一个实体使其得到管理,因此对它的任何改变,即使它们是“临时的”,也将持续存在于flush
上(正如A.Marwan已经在评论中指出的那样)。
由于语义非常清楚,我建议不要在托管的字段(任何映射的字段)上设置临时值。为此添加临时属性或重新评估方法 - 可能是服务或包装或更适合您的用例。
评论更改跟踪政策:
Rikudou_Sennin的答案为技术问题提供了技术上正确的解决方案,当开发人员可能不希望它们通过更改更改跟踪策略时实体得到持久化。恕我直言,这是语义上的邪恶,......好吧,我们称之为有问题。
作为开发人员,我总是假设对象具有一致的状态 - 即使它尚未刷新到数据库。如果它的状态与其持久化版本不同,我想假设,当请求完成,并且所有或没有更改的对象都写入数据库时,数据库处于一致状态。可以假设“无”。 “所有”很难想到。
但是,使用不同的更改跟踪策略和隐含的可能性,“脏”永远不会被信任的对象可能会旋转,开发人员不能以任何方式依赖的值,因为它不清楚,如果对象将被持久化或不,或者可能是坚持。这只会增加更多(不必要的)疑虑。它还是难以调试的错误的另一个来源。
选项摘要:
*)假设有些干净且结构合理的代码,具有完整且不妥协的语义。
您可以通过将Change Tracking Policy
从Deferred Implicit
(默认值)更改为Deferred Explicit
来实现。通过将其更改为显式,只有使用persist()
标记的实体才会保存到数据库中,甚至更新(在implicit
方案中,将跟踪所有更新)。它还有其他的好处,因为它不需要遍历教条存储中的每个对象,因为它不需要遍历那些你用persist()
保存的标记。
以下是通过yaml执行此操作的方法:
type: entity
changeTrackingPolicy: DEFERRED_EXPLICIT # can be DEFERRED_IMPLICIT, DEFERRED_EXPLICIT or NOTIFY
# the rest of your config