在这一点上,我不确定问题出在教义还是symfony。
我有一个名为Field的实体。它具有带有常规getter和setter方法的dataTable属性。在我的一个支持类中,我使用setter方法将dataTable更改为一个临时值。我从不在此类或调用它的控制器中调用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);
}
设置功能:
/**
* @param string $dataTable
*/
public function setDataTable(string $dataTable): void
{
$this->dataTable = $dataTable;
}
答案 0 :(得分:1)
免责声明:默认更改跟踪策略(隐式)适用以下条件
flush
根据定义将对托管实体所做的所有更改都写入数据库。
持久存在一个实体可以对其进行管理和管理,因此对它的任何更改(即使它们被认为是“临时的”)也将保留在flush
上(正如A.Marwan在评论中已经指出的那样)。>
由于语义非常清晰,我建议不要在托管字段(即任何映射字段)上设置临时值。为此添加一个临时属性或重新评估该方法-可能是服务或包装器,或更适合您的用例的任何东西。
更改跟踪策略的评论:
Rikudou_Sennin的答案为技术问题提供了一种技术上正确的解决方案,即当开发人员可能不希望通过更改更改策略来使实体持久化时,实体将保持不变。恕我直言,这在语义上是邪恶,...好吧,我们称之为有问题。
作为开发人员,我将始终假定对象具有一致的状态-即使尚未刷新到数据库中。如果它的状态与其持久版本不同,我想假设当请求完成后,全部或全部的已更改对象都被写入数据库,则该数据库位于一致状态。可以假定为“无”。 “全部”很难思考。
但是,由于采用了不同的变更跟踪策略和隐性可能性,“肮脏的”永不被信任的对象可能会绕来绕去,开发人员无法以任何方式依赖该值,因为尚不清楚该对象是否将被持久化还是被持久化。这只会增加(不必要的)怀疑。这也是难以调试的错误的另一个来源。
选项摘要:
*)假定有些干净且结构正确的代码,且语义完整无缺。
答案 1 :(得分:1)
您可以通过将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