Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否可以逐出spring缓存部分数据?_Java_Spring_Caching_Ehcache_Spring Cache - Fatal编程技术网

Java 是否可以逐出spring缓存部分数据?

Java 是否可以逐出spring缓存部分数据?,java,spring,caching,ehcache,spring-cache,Java,Spring,Caching,Ehcache,Spring Cache,鉴于这些实体和存储库可以访问DDBB中的数据: @Entity public class Customer { Long id; } @Entity public class Purchase { Long customerId; } @Repository public lass PurchaseDAO { public void insert(Purchase insert); public void deleteCustomerPurchases(Long cu

鉴于这些实体和存储库可以访问DDBB中的数据:

@Entity
public class Customer {
Long id;
}

@Entity
public class Purchase {
    Long customerId;
}

@Repository
public lass PurchaseDAO {

   public void insert(Purchase insert);

   public void deleteCustomerPurchases(Long customerId);

   public long getTotalPurchasesAmount(Long customerId);

   public long getTotalPurchasesAmountPerMonth(Long customerId, int month);
}
我想为方法getTotalPurchaseAmounts(longCustomerId)添加缓存,这样,当为客户添加一些购买时,只收回该客户的purchasesd

相关的依赖项包括:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.2</version>
        </dependency>
由于SpringCache(和ehcache)的逐出受元素或所有条目的限制,所以我开发的解决方案是以友好方式创建缓存(每个客户一个),这样我就可以逐出这些缓存

我认为最好的扩展点是实现自定义缓存解析器:

@Component("CustomerPurchasesCacheResolver")
public class CustomerPurchasesCacheResolver implements CacheResolver {

    @Autowired
    private EhCacheCacheManager cacheManager;

    @Override
    public Collection<? extends Cache> resolveCaches( CacheOperationInvocationContext<?> context ) {
        String cacheName = "customerPurchases_" + getCustomerId( context );
        // Add cache to cacheManager if it does not exists
        cacheManager.getCacheManager().addCacheIfAbsent( cacheName );

        Set<Cache> caches = new HashSet<>();
        caches.add( cacheManager.getCache( cacheName ) );
        return caches;
    }

    // Retrieves customerId from cache operation invocation context;
    private Long getCustomerId( CacheOperationInvocationContext<?> context ) {
    String key = ( (CacheOperation) context.getOperation() ).getKey();
        // TODO Evaluate key
        // HOW CAN I DO THIS????????????
        return null;
    }

}
使用此方法的唯一问题是使用Spring表达式计算键


有什么方法可以得到这个结果,或者有一种不同的方法可以工作吗?

为每个客户记录创建缓存是一种过分的做法。使用SpEL,您可以指定要逐出的客户记录的密钥。配置ehcache,以便有一个客户缓存。然后更改PurchaseDAO方法,以便它们指定要缓存或逐出的键。按如下方式更改代码

@CacheEvict(value = "customerCache" , key="#purchase.customerId")       
public void insert(Purchase purchase);

@Cacheable( value = "customerCache" ,key = "#customerId") // you can omit the key if using default key generator as it still uses the method argument
public long getTotalPurchasesAmount(Long customerId);
但是,为了回答有关从CacheResolver获取customerId的问题,CacheOperationInvocationContext有一个getArgs()方法,该方法返回传递给要缓存的方法的参数

 private Long getCustomerId( CacheOperationInvocationContext<?> context ) {
        Object[] args = context.getArgs();
        Object firstArg = args[0];
        if(firstArg instanceof Long){
           return (Long)firstArg;
        }
        else if(firstArg instanceof Purchase){
            Purchase purchase = (Purchase)firstArg;
            return purchase.getCustomerId();
        }
        return null;
    }
private Long getCustomerId(CacheOperationInvocationContext){
对象[]args=context.getArgs();
Object firstArg=args[0];
if(firstArg instanceof Long){
返回(长)第一个参数;
}
else if(购买的第一个参数实例){
采购采购=(采购)第一个参数;
退货采购。getCustomerId();
}
返回null;
}

为每个客户记录创建缓存是一种过分的做法。使用SpEL,您可以指定要逐出的客户记录的密钥。配置ehcache,以便有一个客户缓存。然后更改PurchaseDAO方法,以便它们指定要缓存或逐出的键。按如下方式更改代码

@CacheEvict(value = "customerCache" , key="#purchase.customerId")       
public void insert(Purchase purchase);

@Cacheable( value = "customerCache" ,key = "#customerId") // you can omit the key if using default key generator as it still uses the method argument
public long getTotalPurchasesAmount(Long customerId);
但是,为了回答有关从CacheResolver获取customerId的问题,CacheOperationInvocationContext有一个getArgs()方法,该方法返回传递给要缓存的方法的参数

 private Long getCustomerId( CacheOperationInvocationContext<?> context ) {
        Object[] args = context.getArgs();
        Object firstArg = args[0];
        if(firstArg instanceof Long){
           return (Long)firstArg;
        }
        else if(firstArg instanceof Purchase){
            Purchase purchase = (Purchase)firstArg;
            return purchase.getCustomerId();
        }
        return null;
    }
private Long getCustomerId(CacheOperationInvocationContext){
对象[]args=context.getArgs();
Object firstArg=args[0];
if(firstArg instanceof Long){
返回(长)第一个参数;
}
else if(购买的第一个参数实例){
采购采购=(采购)第一个参数;
退货采购。getCustomerId();
}
返回null;
}

谢谢你,埃肯。问题是,每个客户都会有多条记录(即@Cacheable public int getPurchasesAmountPerMonth(int month)),并且具有不同签名的方法会退出缓存,因此仅获取args[0]并不能完成此任务。你让我意识到我原来的问题缺乏关键信息。我将编辑这篇文章,把这个观点作为问题的重点。谢谢Ekem。问题是,每个客户都会有多条记录(即@Cacheable public int getPurchasesAmountPerMonth(int month)),并且具有不同签名的方法会退出缓存,因此仅获取args[0]并不能完成此任务。你让我意识到我原来的问题缺乏关键信息。我将编辑这篇文章,以表明这是问题的主要观点。