【问题标题】:Doctrine with static entities静态实体的学说
【发布时间】:2018-03-14 15:45:26
【问题描述】:

我有一个数据库,其中存储了一些固定值,例如产品类别。当我创建一个新产品并想为其分配一个类别时,我会这样做:

$categories = new ProductCategoryRepository();
$category = $categories->find(ProductCategory::EXAMPLE);

$product = new Product();
$product->setCategory($category);

但是,我不确定为什么我必须一直查找数据库才能获取我的应用已经知道的静态实体。

静态分配类别就足够了。也许是这样的:

$category = ProductCategory::EXAMPLE;

现在 Doctrine 应该使用正确的 ID(由 ProductCategory 类描述(可能是实体?))保持关系,并且我不再需要在数据库中查找静态属性。

我还不知道该怎么做。我可以一直创建新实体,但这似乎不正确,因为这些值已经存储在数据库中,并且它们始终是相同的,不是新实体。

$category = new ProductCategory::EXAMPLE;

然而,从产品中获取关系应该将属性作为实体返回:

$category = $product->getCategory();

return $category instanceof ProductCategory; // true

有没有办法实现这种行为?

这更像是一个架构问题,而不是性能调整。我不想多次描述信息(db 条目、php 常量、实体关系等)。

【问题讨论】:

  • Doctrine ORM 层处理对象,所以我认为您几乎无法使用类别对象。然而,有一个 EntityManager::getReference('ProductCategory',$id) 方法,它返回一个仅包含 id 的引用类别对象。因此,它减少了正在传输的数据。 docs.doctrine-project.org/projects/doctrine-orm/en/latest/…

标签: php laravel doctrine-orm


【解决方案1】:

Doctrine 中有一个叫做“二级缓存”的东西,但是这个特性被认为是实验性的,你应该在使用它之前仔细阅读文档。 来自the official documentation 对此功能的引用:

二级缓存

二级缓存功能目前被标记为实验性的。这是一个非常复杂的功能,我们还不能保证它在所有情况下都能稳定运行。

实体缓存定义是这样完成的:(documentation)

/**
 * @Entity
 * @Cache(usage="READ_ONLY", region="my_entity_region")
 */

要提高您在问题中所讨论的此类实体的性能,您还应该考虑将它们标记为“只读”,这将导致 Doctrine 2.1 的性能提高,可在 the Doctrine documentation on improving performance 中找到:

只读实体

从 Doctrine 2.1 开始,您可以将实体标记为只读(有关详细信息,请参阅元数据映射参考)。这意味着标记为只读的实体永远不会被考虑更新,这意味着当您在 EntityManager 上调用 flush 时,即使属性发生更改,这些实体也会被跳过。只读允许保留一种新实体并删除现有实体,只是不考虑更新它们。

实体应该这样配置:(documentation)

/** @Entity(readOnly=true) */

二级缓存和只读您的 ProductCategory:

因此,在设置二级只读缓存后,例如使用名为 read_only_entity_region 的区域,您的 ProductCategory 配置将如下所示:

/**
 * @Entity(readOnly=true)
 * @Cache(usage="READ_ONLY", region="read_only_entity_region")
 */
class ProductCategory 
{
    //...your entity definition...
}

【讨论】:

    【解决方案2】:

    如果您不希望它每次都访问数据库,您可以将其存储在缓存中:

    public function getCategory(){
        return Cache::rememberForever('category-'.$this->category_id, function() {
            return $categories->find($this->category_id);
        });
    }
    

    如果从未提取过信息,这将从数据库中提取信息,但如果已提取,则只会从缓存中获取信息。您必须使用Cache::forget('category-2') 将其删除,或者使用php artisan cache:clear。您的静态值将只是整数 ID,您的产品将具有 category_id,但类别本身将被缓存。

    【讨论】:

    • 你真的用 Doctrine 实体尝试过这个吗?通常,实体需要由实体管理器“管理”。参考存储在工作对象的内部单元中。在实体管理器之外创建现有对象很少有好的结果。虽然 Laravel 可能会以某种方式解决这个问题。
    • 诚然我不知道,但我知道 Laravel 缓存支持缓存对象并处理序列化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-08
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多