gpt4 book ai didi

mongodb - Gedmo Timestampable 在使用 JMS Serializer 反序列化时总是更新引用

转载 作者:可可西里 更新时间:2023-11-01 10:43:25 27 4
gpt4 key购买 nike

我在我的 Symfony2 项目中有一个一对一的关系,其中一个 Question 引用了一个 Video - 两者都有一个 created更新 Gedmo\Timestampable 行为,基本上按预期工作。但是有点太多了:

当使用附加的 Video 反序列化 Question 时(作为 ID 只是为了避免 Video 元数据中的其他更改)Video 文档总是created updated 字段上得到更新。这似乎不对。我可能理解为什么更新字段获得新日期 - 即使实际上对象本身没有任何变化,但为什么创建

这是我的代码(已简化):

类问题:

<?php

/**
* Class Question
*
* @Serializer\AccessorOrder("alphabetical")
* @MongoDB\Document(
* collection="Quiz",
* repositoryClass="MyNamespace\Bundle\QuizBundle\Repository\QuestionRepository",
* )
* @package MyNamespace\Bundle\QuizBundle\Document
*/
class Question
{
/**
* @var \MongoId
* @MongoDB\Id(strategy="auto")
* @Serializer\Type("string")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
*/
protected $id;

/**
* @var \DateTime
*
* @Assert\Date(
* message = "quiz:constraints.model.question.created.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getCreated", setter="setCreatedEmpty")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @Gedmo\Timestampable(on="create")
* @MongoDB\Date
*/
protected $created;


/**
* @var \DateTime
*
* @Assert\Date(
* message = "quiz:constraints.model.question.updated.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getUpdated", setter="setUpdatedEmpty")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @Gedmo\Timestampable(on="update")
* @MongoDB\Date
*/
protected $updated;

/**
* @var Video
*
* @Serializer\Type("MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video")
* @Serializer\Groups({
* "quiz_admin_list",
* "quiz_admin_detail"
* })
* @MongoDB\ReferenceOne(
* targetDocument="MyNamespace\Bundle\CoreMediaAdminBundle\Document\Video",
* cascade={"all"}
* )
*/
protected $answerVideo;

}

类视频:

<?php

/**
* Class Video
* @Serializer\AccessorOrder("alphabetical")
* @MongoDB\Document(
* collection="CoreMediaAdminVideo",
* repositoryClass="MyNamespace\Bundle\CoreMediaAdminBundle\Repository\VideoRepository",
* )
* @Vich\Uploadable
* @package MyNamespace\Bundle\CoreMediaAdminBundle\Document
*/
class Video
{

/**
* @MongoDB\Id(strategy="auto")
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
*/
protected $id;

/**
* @Vich\UploadableField(
* mapping = "core_media_admin_video",
* fileNameProperty = "fileName"
* )
* @Serializer\Exclude
* @var File $file
*/
protected $file;

/**
* @MongoDB\Field(type="string")
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
*/
protected $mimeType;

/**
* @var String
*
* @Assert\NotBlank(
* message = "core.media.admin:constraints.model.base.title.not_blank"
* )
* @Serializer\Type("string")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @MongoDB\Field(type="string")
*/
protected $title;

/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Accessor(getter="getCreated", setter="setCreatedEmpty")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="create")
* @MongoDB\Date
*/
protected $created;

/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* _Serializer\Accessor(getter="getUpdated", setter="setUpdatedEmpty")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="update")
* @MongoDB\Date
*/
protected $updated;

/**
* @var \DateTime
*
* @Assert\Date(
* message = "core.media.admin:constraints.model.base.date.invalid"
* )
* @Serializer\Type("DateTime<'U'>")
* @Serializer\Groups({
* "core_media_list",
* "core_media_search",
* "core_media_video_list",
* "core_media_video_detail"
* })
* @Gedmo\Timestampable(on="update", field={"title", "tags", "comment", "dataOrigin", "description", "videoMetaData", "mimeType", "fileName", "file" })
* @MongoDB\Date
*/
protected $updatedContent;

}

有趣的是,在反序列化期间没有对 Video 对象进行任何更改 - 只有更新查询来设置 created 和视频的 updated 字段。我还测试了 Timestampable 的 field 参数,仅当其中一个字段获得更新时才强制更新,但这似乎被完全忽略了。

这里也是反序列化的JSON和相应的MongoDB查询:

{
"id": "547f31e650e56f2c26000063",
"question_id": 12,
"question_text": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
"answer_text": "test",
"answer_video": {
"id": "547f31d850e56f2c26000031"
},
"tags": [
"Schnecken",
"Basilikum",
"Thymian",
"Garten"
]
}

查询:

db.QuizQuestion.find({
"_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();

db.CoreMediaAdminVideo.update({
"_id": ObjectId("547f31d850e56f2c26000031")
},
{
"$set": {
"created": newISODate("2014-12-03T21:30:02+01:00"),
"updated": newISODate("2014-12-03T21:30:02+01:00"),
"updatedContent": newISODate("2014-12-03T21:30:02+01:00")
}
});

db.ARDBuffetQuizQuestion.update({
"_id": ObjectId("547f31e650e56f2c26000063")
},
{
"$set": {
"created": newISODate("2014-12-03T21:30:02+01:00"),
"updated": newISODate("2014-12-03T21:30:02+01:00"),
"questionText": "Wer einen Gemüsegarten hat, sollte wissen, dass Schnecken…?",
"answerText": "test",
"answerVideo": {
"$ref": "CoreMediaAdminVideo",
"$id": ObjectId("547f31d850e56f2c26000031"),
"$db": "my-database"
}
}
});

db.ARDBuffetQuizQuestion.update({
"_id": ObjectId("547f31e650e56f2c26000063")
},
{
"$set": {
"tags": [
{
"value": "Schnecken",
"normalized": "schnecken"
},
{
"value": "Basilikum",
"normalized": "basilikum"
},
{
"value": "Thymian",
"normalized": "thymian"
},
{
"value": "Garten",
"normalized": "garten"
}
]
}
});

db.ARDBuffetQuizQuestion.find({
"_id": ObjectId("547f31e650e56f2c26000063")
}).limit(1).limit();

db.CoreMediaAdminVideo.find({
"_id": ObjectId("547f31d850e56f2c26000031")
}).limit(1).limit();

最佳答案

Gedmo\Timestampable 将为 $created$updated 设置(新)值,因为刷新 ObjectManager 时该数据不存在。

尽管 Video 类中的注释定义了在序列化此类对象时应包含 $created$updated,但您显示的 JSON不包含那些键/属性。

这是发生了什么:

  • JSON 不包含创建更新 的键/属性。
  • 反序列化时,生成的对象将具有 $created$updatednull 值。
  • merge() 将对象放入 ObjectManager 时,它没有任何反应。该对象简单地变为“托管”,这意味着在刷新期间,ObjectManager 将为它计算变更集并在必要时更新它。
  • 当刷新 ObjectManager 时,Gedmo\Timestampable 将启动(由于 PreUpdate 事件监听器)。它将看到 $created$updated 包含 null 值,因此它将分配新值。
  • 然后 ObjectManager 将从数据库中检索“当前”数据,因为它需要它来计算变更集。通常,当 find() 搜索一个对象时,它不会执行此操作,因为数据已经在 find() 期间检索到。
  • 因为 $created$updated 的值现在与从数据库中检索到的值不同,它将更新它们。

所以你有两个选择:

  1. find() 对象,然后根据JSON改变它。
  2. 确保 JSON 包含映射的所有属性(包括createdupdated)。

另外,我注意到 setter="setCreatedEmpty"setter="setUpdatedEmpty"。我不确定这些方法的作用(因为您没有向我们展示),但是方法名称表明了其他一些简单地赋值的东西。

回复您的评论

merge() 将一个对象放入 ObjectManager 时,它被标记为“脏”,这将触发变更集的计算。并且由于 DateTime 对象的引用发生了变化(Doctrine 从数据库中获取的实例总是与通过反序列化 JSON 创建的实例不同),该对象将被更新。然后 Gedmo\Timestampable 将启动并相应地更改 $updated 属性。

如果您不希望这种情况发生,您需要find() 当前对象,并且在值对象实际表示的值时更改值对象变了。标量值没有问题:你可以设置相同的值,Doctrine 不会将其视为更改。但是对于值对象(如 DateTime)对象,Doctrine 会在引用发生变化时(当设置了不同的实例时)看到变化。

关于mongodb - Gedmo Timestampable 在使用 JMS Serializer 反序列化时总是更新引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27281468/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com