Spring Arangodb存储Edge报MappingException: 找不到java.lang.Object的PersistentEntity
异常产生原因
- 核心原因是Java的泛型擦除机制结合Spring Data ArangoDB的实体映射规则导致的:你定义的
Link2User<T>边类中,@To标注的to字段是泛型类型,运行时泛型T会被擦除为java.lang.Object。 - 数据能成功写入是因为序列化阶段你传入的实例是具体的
Item类型,ArangoDB驱动可以正常序列化数据写入数据库。但写入完成后Spring Data需要将返回的数据库结果映射回实体类时,会尝试获取to字段类型对应的持久化实体元数据,而Object没有被注册为持久化实体,因此抛出MappingException。 - 另外你提供的代码存在笔误:注入的Repository变量名是
l2uRepository,调用save方法时用的是v2uRepository,实际运行时会先报空指针,需要先修正这个笔误。
解决方案
方案1:为不同目标实体单独定义边类(最推荐)
直接抛弃泛型边类的设计,针对不同的@To目标类型定义独立的边类和对应Repository,完全规避泛型擦除问题:
// 关联Item的边类 @Data @Edge("link2User") public class Link2UserToItem { @Id private String key; @From private User user; @To private Item to; private String data; // 构造方法 } // 对应Repository public interface Link2UserToItemRepository extends ArangoRepository<Link2UserToItem, String> { }
不同类型的关联边可以共用同一个ArangoDB边集合,只要@Edge注解指定的集合名相同即可,不会额外占用存储空间。
方案2:给泛型添加上边界
如果需要复用边类代码,可以给泛型添加上边界,上边界为所有实体类的公共父类,且父类需要标注@Document注解让Spring Data识别:
// 公共实体父类 @Document public class BaseEntity { // 公共字段比如id等 } // 边类修改为 public class Link2User<T extends BaseEntity> { @To private T to; // 其余代码不变 } // Item、User等实体都继承BaseEntity
方案3:定义具体类型的Repository子类
保留泛型边类,不要使用泛型的Link2UserRepository<T>,而是为每个具体类型编写单独的Repository子类:
// 泛型边类保留 public class Link2User<T> { // 原有代码不变 } // 不要用泛型Repository,改为对每个目标类型写独立Repository public interface Link2UserItemRepository extends ArangoRepository<Link2User<Item>, String> { } // 注入时使用具体的子类Repository @Autowired Link2UserItemRepository l2uRepository;
内容的提问来源于stack exchange,提问作者Michal
相关产品推荐
相关产品推荐

