【问题标题】:Spring repository auto casts entities with different class typesSpring存储库自动转换具有不同类类型的实体
【发布时间】:2015-07-10 00:41:42
【问题描述】:

我正在使用 MongoRepository 接口为不同的实体扩展我的自定义存储库。现在我遇到了问题,让我们假设一个例子: 我有 2 个实体:

@Document(collection = "person")
public class Employee {
    private String position;
}

@Document(collection = "person")
public class Manager {
    private String major;
}

两者的存储库:

@Repository
public interface ManagerRepository extends MongoRepository<Manager, String> {}

@Repository
public interface EmployeeRepository extends MongoRepository<Employee, String> {}

当我保存 2 个模型时一切顺利:

{
    "_id" : ObjectId("5541f988d4c603ebac18a147"),
    "_class" : "com.igmtechnology.gravity.core.init.test.Manager",
    "major" : "majority"
}
{
    "_id" : ObjectId("5541f988d4c603ebac18a148"),
    "_class" : "com.igmtechnology.gravity.core.init.test.Employee",
    "position" : "developer"
}

但是当我从一个存储库中执行 findAll() 时,我得到了 2 个对象,其中一个 spring 自动转换为另一个。 如何避免这种自动铸造?或者如何指定我需要获取哪个类?

【问题讨论】:

    标签: java spring mongodb spring-data


    【解决方案1】:

    对于这两个存储库,您可以使用 @Query 注释指定将使用的 MongoDB JSON 查询字符串,而不是从方法名称派生的查询(您必须知道解析存储库的方法名称有一个约定并用于构建 MongoDB 查询)。

    所以,通过使用@Query,您可以:

    @Repository
    public interface ManagerRepository extends MongoRepository<Employee, String>
    
      @Query(value="{ '_class' : 'com.igmtechnology.gravity.core.init.test.Manager' }")
      List<Person> findAllManagers();
    
    }
    

    在幕后,这将生成一个查询,类似于这个:

    db.person.findAll({'_class' ; 'com.igmtechnology.gravity.core.init.test.Manager'});
    

    但是,此代码存在一个小问题。如果您更改 Manager 的完全限定类名,则查询不会抛出 RuntimeException,但不会返回任何内容。在这种情况下,您可以在 @Query 中使用通配符。

    @Query(value="{ '_class' : ?0 }")
    List<Person> findAllManagers(String className);
    

    然后,当您调用该方法时,您可以这样做:

    managerRepository.findAllManagers(Manager.class.getName());
    

    提供的Manager.class.getName() 将替换?0 通配符,您的查询将正确构建。

    Employee 存储库也是如此,不同之处在于您必须在@Queryvalue 属性中提供Employee 的完全限定类名。

    更多信息:

    【讨论】:

    • 感谢您的回答。我知道这种解决方案,但我不太喜欢它,因为如果我的实体会更改 com.igmtechnology.gravity.core.init.test.Manager -> com.solution.test.Manager 我不会赶上运行时间错误,但总会找到空List。
    • 是的,它工作正常,这是一个很好的解决方案!最后一个问题 - 如果查询将有更多条件,例如 - 'name',我该怎么办?如果我添加像 @Query("{'_class' : ?0, 'name' : ?1}") List findAllManagersByName(String className, String name); 这样的方法它会正常工作,但如果“名称”将被重命名,仍然会出现问题。是否有更多标准的类似解决方案?
    • 不,我不认为通配符对键有效,但仅对值占位符有效
    • @maxi 可以使用@TypeAlias,它将使用给定的值作为实体类名的替换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    相关资源
    最近更新 更多