saveAndFlush抛出异常时如何使@Cachable缓存失效?

问题描述 投票:0回答:1

当我获得带有

GlobalData
get(Class<T> clazz)
实例时,结果实体中的
data
为 null。

过滤掉日志后,发现有一个searize错误,导致

globalDataRepository.insert(data);
行抛出异常,但同时,错误的数据已经被
@Cachable
DataModelRepository
的机制缓存了。

get(Class<T> clazz)

public <T extends GlobalPersistable> T get(Class<T> clazz) {
        int datatype = PersistableConverter.getDataType(clazz);
        GlobalData data = globalDataRepository.select(datatype);
        if (data == null) {
            synchronized (this) {
                if ((data = globalDataRepository.select(datatype)) == null) {
                    try {
                        data = new GlobalData<>();
                        data.setType(datatype);
                        data.setData(clazz.newInstance());
                        data = globalDataRepository.insert(data);
                    } catch (Exception e) {
                        log.error("", e);
                        return null;
                    }
                }
            }
        }
        return (T) data.getData();
    }

GlobalData

@Data
@Entity
@Table(name = "global_data")
public class GlobalData<T extends Persistable> implements DataModel<Integer> {

    @Id
    private int type;

    @Column(columnDefinition = "MEDIUMBLOB")
    @Convert(converter = PersistableConverter.class)
    private Persistable data;


    @Override
    public Integer getPK() {
        return type;
    }

    @SuppressWarnings("unchecked")
    public T getData() {
        return (T) data;
    }
}

存储库:

public interface DataModelRepository<T extends DataModel<PK>, PK> extends AppRepository<T, PK> {
    String CACHE_NAME = "repository";

    @Cacheable(cacheNames = CACHE_NAME, key = "#root.target.class.getInterfaces()[0].getSimpleName() + '@' + #pk", unless = "#result==null")
    default T select(PK pk) {
        return findById(pk).orElse(null);
    }

    @CachePut(cacheNames = CACHE_NAME, key = "#root.target.class.getInterfaces()[0].getSimpleName() + '@' + #entity.getPK()")
    default T insert(T entity) {
        return saveAndFlush(entity);
    }

    @Override
    @CacheEvict(cacheNames = CACHE_NAME, key = "#root.target.class.getInterfaces()[0].getSimpleName() + '@' + #entity.getPK()")
    void delete(@Nonnull T entity);


}

如果

insert
抛出异常,如何删除缓存?或者缓存实体直到插入正确完成?

java jpa
1个回答
0
投票

如果该方法抛出异常,您可以捕获它并调用cancel方法。

这是我想到的最快的方法。 例如

public <T extends GlobalPersistable> method(String key) {
    try {
        return callMethodWithCacheable(key);
    } catch (Exception e) {
        callMethodWithEvict(key);
        return null;
    }

}

另一种方法是在调用 saveAndFlush 的方法中捕获异常并返回 Either (https://medium.com/disney-streaming/option-either-state-and-io-imperative-programming-in-a- function-world-8e176049af81#:~:text=In%20theory%2C%20Either%20can%20represent,a%20failure%20of%20type%20A%20.),如果 Either 包含填充的左侧位置,则调用删除方法

例如

 public  <T extends GlobalPersistable> method(String key) {

    Either<Error, Success> successErrorEither = SafeExecution.exec(() -> callMethodWithCacheable(key));
    if (successErrorEither.isLeft()) {
        callMethodWithEvict(key);
        return null; //In this point for me is better return Optional
    } else {
        return successErrorEither.getRight();
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.