我怎样才能防止不需要的学说在 symfony 4 中持续存在?
How can I prevent unwanted doctrine persists in symfony 4?
在这一点上,我不确定问题是出在教义上还是出在 symfony 上。
我有一个名为 Field 的实体。它有一个 属性 数据表,带有常用的 getter 和 setter 方法。在我的支持 classes 之一中,我使用 setter 方法将 dataTable 更改为临时值。我从不在这个 class 或调用它的控制器中调用 persist 。但是,我发现数据库正在使用这个临时值进行更新。
如果需要,我可以添加一个虚拟 属性 并改为使用它,但我认为如果我可以避免这种情况,代码会更清晰。我怎样才能确保教义只坚持我明确告诉它的事情?
实体映射:
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);
}
Setter 函数:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
免责声明:以下内容适用于默认更改跟踪策略(隐式)
flush
根据定义将对托管实体所做的任何更改写入数据库。
持久化一个实体使其得到管理,因此对其进行的任何更改,即使它们本来是 "temporary" 也会在 flush
上持久化(正如 A.Marwan 已经指出的那样一条评论)。
由于语义非常清楚,我建议不要在托管字段(任何映射字段)上设置临时值。为此添加一个临时 属性 或重新评估该方法 - 可能是服务或包装器或更适合您的用例的任何东西。
更改跟踪政策的评论:
Rikudou_Sennin 的回答为技术问题提供了技术上正确的解决方案,当开发人员可能不希望实体被持久化时......通过更改更改跟踪策略。恕我直言,这在语义上 邪恶 ,...好吧,我们称之为有问题的。
作为一名开发人员,我总是假设对象具有一致的状态 - 即使它尚未刷新到数据库。如果它的状态与其持久版本不同,我想假设,当请求完成时,all 或 none 已更改的对象被写入数据库,数据库处于一致状态。 "None" 可以假设给出。 "All" 想想就够难的了。
然而,使用不同的更改跟踪策略和隐含的可能性,"dirty" 永远不会被信任的对象可能会旋转,其值开发人员不能以任何方式依赖,因为它不清楚,如果对象将被持久化或不被持久化,或者可能被持久化。这只会增加更多(不必要的)疑虑。它还是难以调试错误的另一个来源。
选项汇总:
- 添加临时字段(或额外的 var/object 或其他):合理的努力并且对语义(和假设)没有影响*
- 更改跟踪策略和误用字段:首次使用工作量低,未知(可能难以理解)未来工作量,语义和假设的丢失(应该需要明确声明的保证,即使那样!)。
*) 假设有点 干净且结构正确的代码,具有完整和不妥协的语义。
您可以通过将 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
在这一点上,我不确定问题是出在教义上还是出在 symfony 上。
我有一个名为 Field 的实体。它有一个 属性 数据表,带有常用的 getter 和 setter 方法。在我的支持 classes 之一中,我使用 setter 方法将 dataTable 更改为临时值。我从不在这个 class 或调用它的控制器中调用 persist 。但是,我发现数据库正在使用这个临时值进行更新。
如果需要,我可以添加一个虚拟 属性 并改为使用它,但我认为如果我可以避免这种情况,代码会更清晰。我怎样才能确保教义只坚持我明确告诉它的事情?
实体映射:
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);
}
Setter 函数:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
免责声明:以下内容适用于默认更改跟踪策略(隐式)
flush
根据定义将对托管实体所做的任何更改写入数据库。
持久化一个实体使其得到管理,因此对其进行的任何更改,即使它们本来是 "temporary" 也会在 flush
上持久化(正如 A.Marwan 已经指出的那样一条评论)。
由于语义非常清楚,我建议不要在托管字段(任何映射字段)上设置临时值。为此添加一个临时 属性 或重新评估该方法 - 可能是服务或包装器或更适合您的用例的任何东西。
更改跟踪政策的评论:
Rikudou_Sennin 的回答为技术问题提供了技术上正确的解决方案,当开发人员可能不希望实体被持久化时......通过更改更改跟踪策略。恕我直言,这在语义上 邪恶 ,...好吧,我们称之为有问题的。
作为一名开发人员,我总是假设对象具有一致的状态 - 即使它尚未刷新到数据库。如果它的状态与其持久版本不同,我想假设,当请求完成时,all 或 none 已更改的对象被写入数据库,数据库处于一致状态。 "None" 可以假设给出。 "All" 想想就够难的了。
然而,使用不同的更改跟踪策略和隐含的可能性,"dirty" 永远不会被信任的对象可能会旋转,其值开发人员不能以任何方式依赖,因为它不清楚,如果对象将被持久化或不被持久化,或者可能被持久化。这只会增加更多(不必要的)疑虑。它还是难以调试错误的另一个来源。
选项汇总:
- 添加临时字段(或额外的 var/object 或其他):合理的努力并且对语义(和假设)没有影响*
- 更改跟踪策略和误用字段:首次使用工作量低,未知(可能难以理解)未来工作量,语义和假设的丢失(应该需要明确声明的保证,即使那样!)。
*) 假设有点 干净且结构正确的代码,具有完整和不妥协的语义。
您可以通过将 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