@ManyToMany 关系的 ebean 缓存问题

时间:2021-03-19 13:09:43

标签: java spring-boot caching redis ebean

当我尝试使用 ebean 缓存系统(使用 io.ebean:ebean-redis)基本上读取 @ManyToMany 关系时出现异常。这是一个 SpringBoot 应用程序。

我使用的版本:

  • springBootVersion=2.4.3
  • mariaDbVersion=2.7.2
  • ebeanVersion=12.7.2
  • flywayVersion=7.7.0

BaseModel Java 类:

@MappedSuperclass
public abstract class BaseModel extends Model {

    @Id
    @GeneratedValue
    private Long id;

    @WhenCreated
    @NotNull
    private Instant createdAt;

    @WhenModified
    @NotNull
    private Instant updatedAt;

    @NotNull
    @SoftDelete
    private Boolean deleted = false;

    protected BaseModel() {
    }

    // here the getters and setters
}

文章 Java 类:

@Entity
@Table(name = "article")
@Cache
public class DArticle extends BaseModel {

    private static final long serialVersionUID = -7120023327129825322L;

    @NotNull
    @Index
    @Length(20)
    private String code;

    @DbJson
    @NotNull
    private Map<Locale, String> name;

    @NotNull
    private Double unitPrice;

    @ManyToMany(mappedBy = "articles")
    private List<DArticleCategory> articleCategories;

    public DArticle(String code, Map<Locale, String> name, Double unitPrice) {
        super();
        this.code = code;
        this.name = name;
        this.unitPrice = unitPrice;
    }

    // here the getters and setters
}

ArticleCategory Java 类:

@Entity
@Table(name = "article_category")
@Cache
public class DArticleCategory extends BaseModel {

    private static final long serialVersionUID = 528512691717594544L;

    @DbJson
    @NotNull
    private Map<Locale, String> name;

    @ManyToMany
    private List<DArticle> articles;

    public DArticleCategory(Map<Locale, String> name) {
        super();
        this.name = name;
    }

    // here the getters and setters

}

SQL(我使用 flyway 进行迁移):

create table `article` (
  `id`                            bigint auto_increment not null,
  `created_at`                    datetime(6) not null,
  `updated_at`                    datetime(6) not null,
  `deleted`                       tinyint(1) not null,
  `code`                          varchar(20) not null,
  `name`                          longtext not null,
  `unit_price`                    double not null,
  primary key (`id`),
  index (`code`)
);

create table `article_category` (
  `id`                            bigint auto_increment not null,
  `created_at`                    datetime(6) not null,
  `updated_at`                    datetime(6) not null,
  `deleted`                       tinyint(1) not null,
  `name`                          longtext not null,
  primary key (`id`)
);

我尝试执行的代码:

DArticleCategory c = new DArticleCategory(getTranslatedText("Category 1", "Catégorie 1", null));
c.save();

DArticleCategory cat = articleCategoryRepository.findById(1l);
for (DArticle article : cat.getArticles()) {
    //nothing
}

例外:

Caused by: java.lang.RuntimeException: Failed to decode cache data
    at io.ebean.redis.encode.EncodePrefixKey.encode(EncodePrefixKey.java:26)
    at io.ebean.redis.RedisCache.key(RedisCache.java:85)
    at io.ebean.redis.RedisCache.get(RedisCache.java:139)
    at io.ebeaninternal.server.deploy.BeanDescriptorCacheHelp.manyPropGet(BeanDescriptorCacheHelp.java:277)
    at io.ebeaninternal.server.deploy.BeanDescriptorCacheHelp.manyPropLoad(BeanDescriptorCacheHelp.java:297)
    at io.ebeaninternal.server.deploy.BeanDescriptor.cacheManyPropLoad(BeanDescriptor.java:1306)
    at io.ebeaninternal.server.loadcontext.DLoadManyContext$LoadBuffer.loadMany(DLoadManyContext.java:215)
    at io.ebean.common.AbstractBeanCollection.lazyLoadCollection(AbstractBeanCollection.java:101)
    at io.ebean.common.BeanList.init(BeanList.java:139)
    at io.ebean.common.BeanList.iterator(BeanList.java:335)
    at db.migration.dev.V2_0_1__katel_test.migrate(V2_0_1__katel_test.java:200)
    at org.flywaydb.core.internal.resolver.java.JavaMigrationExecutor.executeOnce(JavaMigrationExecutor.java:61)
    ... 59 common frames omitted
Caused by: java.lang.IllegalStateException: Expecting String keys but got type:class java.lang.Long
    at io.ebean.redis.encode.EncodePrefixKey.encode(EncodePrefixKey.java:19)
    ... 70 common frames omitted

看起来很简单的代码,但我看不出哪里错了...

1 个答案:

答案 0 :(得分:0)

注解@Cacheable 仅适用于允许拦截器的公共公开方法。但是如果需要,您可以获得“CacheManager”服务并在您的代码中使用它来内部处理私有方法中的缓存。但只是为了解决一些“特殊”问题,通常的方法是对公共方法进行注释。

此外,如果您只使用 starter,那么您只使用了 Spring 的基本和糟糕的实现,一个简单的内存缓存。

考虑您的应用程序将如何工作(单个应用程序、分布式应用程序、缓存的短/长数据量……)以及添加任何支持的缓存管理器(如 ehCache、Hazelcast、Caffeine)的依赖项的内存消耗,...满足您的要求并提高您的缓存性能。