【问题标题】:Spring data elasticsearch: Using @Document annotation on POJO interface class not workingSpring data elasticsearch:在POJO接口类上使用@Document注释不起作用
【发布时间】:2021-11-09 08:20:24
【问题描述】:

我正在将应用程序迁移到最新的 spring-boot 版本(使用 maven spring-boot-dependencies 和版本 2.5.4)。

我有一个名为 Customer 的接口,我有该接口的两个实现(BusinessCustomerPrivateCustomer

三个类的注释是这样的:

@Document(indexName = "customers", type = "customer")
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "customerType"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = BusinessCustomer.class, name = "BUSINESS_CUSTOMER"),
        @JsonSubTypes.Type(value = PrivateCustomer.class, name = "PRIVATE_CUSTOMER")
})
public interface Customer {
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "customerType",
        defaultImpl = BusinessCustomer.class
)
@Entity
@Document(indexName = "customers", type = "customer")
public class BusinessCustomer implements Serializable, Customer, Cloneable {
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "customerType",
        defaultImpl = PrivateCustomer.class
)
@Entity
@Document(indexName = "customers", type = "customer")
public class PrivateCustomer implements Serializable, Customer, Cloneable {

为了查询索引“客户”,我曾经有如下代码:

elasticsearchOperations.count(query, Customer.class);

但这不再起作用了。我在运行时遇到错误:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate Customer using constructor NO_CONSTRUCTOR with arguments ] with root cause org.springframework.beans.BeanInstantiationException: Failed to instantiate [Customer]: Specified class is an interface

像这样在同一个索引中不能再有两个不同的类了吗?现在是否可以通过 ElasticsearchCustomConversions 以某种方式完成?

【问题讨论】:

  • 从错误看来,构造函数不再可见。你能展示一下 POJO 是如何定义的吗?你用龙目岛吗?
  • @AbishekStephen Customer 类中没有构造函数,因为它是一个接口。不使用龙目岛。完整的异常是:Servlet.service() for servlet [dispatcherServlet] in context with path [] throw exception [Request processing failed;嵌套异常是 org.springframework.data.mapping.model.MappingInstantiationException:无法使用带参数的构造函数 NO_CONSTRUCTOR 实例化客户,根本原因是 org.springframework.beans.BeanInstantiationException:无法实例化 [客户]:指定的类是一个接口跨度>
  • > 无法实例化 [Customer]: Specified class is an interface 这意味着您的 JsonTypeInfo 未正确映射到其子类型 JsonSubTypes。有什么方法可以在 JsonTypeInfo 声明中表示接口 Customer.class 吗?
  • @AbishekStephen 到目前为止,jackson 注释中没有任何变化。我认为问题在于:“Spring Data Elasticsearch 的早期版本使用基于 Jackson 的转换,Spring Data Elasticsearch 3.2.x 引入了元模型对象映射。”我不知道如何用新的元模型而不是杰克逊注解来指定子类型关系。
  • 也许stackoverflow.com/questions/68861361/… 也与我的问题有关。

标签: java spring spring-boot elasticsearch spring-data-elasticsearch


【解决方案1】:

Spring Data Elasticsearch 中的MappingElasticsearchConverter 不适用于接口,但依赖于在实体类上设置的@Document@Field 注释。

所有 Spring Data 模块——不仅是 Spring Data Elasticsearch——使用PersistentEntity 的概念,这是关于要存储的类的元信息。而PersistentPropertys,这是关于类属性的元信息。对于 Spring Data Elasticsearch,这是有关 Elasticsearch 中字段名称的信息,它的类型, 日期格式等信息。

@Document 注释类与索引相关联。从版本 7 开始,Elasticsearch 不再支持在一个索引中包含多种类型。

因此,您应该将不同的实体存储在两个索引中:

@Document(indexName="business-customers")
class BusinessCustomer {
    // ...
}

@Document(indexName="private-customers")
class PrivateCustomer {
    // ...
}

在一次调用中从这两个索引中搜索并返回不同的数据是可能的,我写了一篇关于如何做到这一点的博客文章 (https://www.sothawo.com/2021/05/reading-different-entities-from-multiple-indices-with-one-call-using-spring-data-elasticsearch/)。

【讨论】:

    猜你喜欢
    • 2015-06-12
    • 1970-01-01
    • 2021-03-26
    • 2019-11-09
    • 2013-12-27
    • 2018-05-13
    • 2017-10-29
    • 2021-11-19
    相关资源
    最近更新 更多