有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaSpringDataMongoDB存储库没有正确实现继承

具有两种类型的实体,映射到单个MongoDB集合中的两个Java类:

@Document
public class Superclass { ... }

@Document(collection = "superclass")
public class Subclass extends Superclass { ... }

这些实体有两个存储库:

public interface SuperclassRepository extends MongoRepository<Superclass, String> {}
public interface SubclassRepository extends MongoRepository<Subclass, String> {}

MongoRepositories无法正确处理实体的继承。在查询所有Subclass对象(例如SubclassRepository.findAll())时,结果集包含Superclass对象,这些对象被实例化(或至少已尝试实例化)为属于Subclass一部分但不属于Superclass的字段的空值

预期的结果是SubclassRepository应该只返回Subclass对象,而SuperclassRepository应该返回SuperclassSubclass对象。它在Spring数据JPA中就是这样工作的

有没有人遇到过这个错误,并且有任何解决方法来修复它


共 (1) 个答案

  1. # 1 楼答案

    我遇到了同样的问题

    看看源代码,让我惊讶的是它没有实现。它会添加集合名称和实体类,但不会在最终查询中插入_class属性。 看了之后,我意识到Mongo是如何知道子类1或子类2是从超类派生出来的。 因此,我只需重写SimpleMongoRepository类,并创建自己的工厂,将该类而不是默认的SimpleMongoRepository放入其中

    我补充说:

    public MySimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
    
        Assert.notNull(mongoOperations);
        Assert.notNull(metadata);
    
        this.entityInformation = metadata;
        this.mongoOperations = mongoOperations;
        Reflections reflections = new Reflections("com.cre8techlabs.entity");
        Set<String> subTypes = reflections.getSubTypesOf(entityInformation.getJavaType()).stream().map(Class::getName).collect(Collectors.toSet());
        subTypes.add(entityInformation.getJavaType().getName());
        this.baseClassQuery = Criteria.where("_class").in(subTypes.toArray());
    }
    

    这里是一个find的实现示例

    public T findOne(ID id) {
        Assert.notNull(id, "The given id must not be null!");
        Query q = getIdQuery(id).addCriteria(baseClassQuery);
    
        return mongoOperations.findOne(q, entityInformation.getJavaType(), entityInformation.getCollectionName());
    }
    

    这对我来说很管用,我只是担心它需要更长的时间