Doctrine2二级缓存仅使用ID而没有关联

时间:2016-05-13 06:47:54

标签: php symfony doctrine-orm

所以,我们有两个实体

ProductBrand

AppBundle\Entity\Brand:
    type: entity
    id:
        id:
            type: integer
            generator:
                strategy: AUTO
    cache:
        usage : READ_ONLY
        region : region_products
    oneToMany:
        products:
            targetEntity: AppBundle\Entity\Product
            mappedBy: brand
            cache:
                usage : READ_ONLY
            cascade: ["remove", "persist"]
            orderBy: { 'name': 'ASC' }


AppBundle\Entity\Product:
    type: entity
    cache:
        usage : READ_ONLY
        region : region_products
    id:
        id:
            type: integer
            generator:
                strategy: AUTO

    manyToOne:
        brand:
            targetEntity: AppBundle\Entity\Brand
            inversedBy: products
            joinColumns:
                brand_id:
                    referencedColumnName: id
            cache:
                usage : READ_ONLY

我们已经使用Redis配置了Doctrine2 2lc

services:
    snc_second_level_cache:
        class: "%snc_redis.doctrine_cache_phpredis.class%"
        calls:
            - ["setRedis", ["@snc_redis.second_level_cache"]]
            - ["setNamespace", ["slc_"]]

doctrine:
    orm:
        result_cache_driver: redis
        metadata_cache_driver: redis
        query_cache_driver: redis
        second_level_cache:
            region_cache_driver:
                type: service
                id: snc_second_level_cache
            region_lock_lifetime: 60
            log_enabled: true
            region_lifetime: 300
            enabled: true
            regions:
                region_products:
                    cache_driver:
                        type: service
                        id: snc_second_level_cache
                    lifetime: 300

我们想要做的是缓存每个Brand及其相关的Product,因此如果我们在缓存中检索Brand,它就会给我们提供这样的信息。 s Product也是。

根据Doctrine的文档,我们最终得到了上述配置和此查询。

$em = $this->get('doctrine.orm.entity_manager');
$result = $em->getRepository('AppBundle:Brand')->findAll();

这实际上把我们所有的品牌都放到了Redis中,如果我们再次进行查询,不是在MySQL中触发而是在Redis中触发,这是可以的。

但是在某些情况下,我们无法理解正在发生的事情

  1. 使用->find($id)点击缓存并从中检索Brand Redis,但使用->findOneBy(array('name' => 'foo'));不是 从Redis获取,它进行MySQL查询,然后缓存两者, 查询和结果到Redis,然后,第二次执行 查询,您从Redis获得foo品牌。如果2lc缓存整个 实体,为什么它不试图找到name字段?这是 实际上在Redis!

  2. 使用$result->getProducts()创建一个MySQL 查询和缓存生成的实体,并不是它的用途 已经在Redis,因为我们已经配置了这种方式? (缓存在 YAML注释到关联映射中)

1 个答案:

答案 0 :(得分:0)

您正在使用Redis,但它可能是另一个缓存引擎(或存在于文件中)。什么是缓存是结果的序列化作为键/值。它没有使用Redis NoSQL系统来查询redis中的结构化对象,如果它正是您要查找的内容。

缓存中的内容是尽可能原子序列化结果的关键值。因此,在sql查询中,您拥有所有主键,然后查询的所有对象都将在缓存中单独获取。因此,如果您更新自己的某个品牌,则不需要使与其相关的所有缓存无效,而只需将包含该品牌的条目无效。

对于您的Brand->产品,它是同一件事,产品缓存条目是一个只包含产品ID的集合,第一次调用getProducts将触发查询,第二次它会不