DateBridge для ZonedDateTime в спящем поиске дает исключение при индексации данных - PullRequest
3 голосов
/ 27 января 2020

У моего объекта есть поле ZonedDatetime

@Indexed
@Entity
public class Book {
    @Id 
    private Long id;
    @Field
    @DateBridge(resolution = Resolution.SECOND)
    private ZonedDateTime createdAt;

    // Other fields and setters & getters
}

, когда я пытаюсь сохранить объект, приложение выдает ниже исключения

    field bridge: TwoWayString2FieldBridgeAdaptor [stringBridge=org.hibernate.search.elasticsearch.bridge.builtin.time.impl.ElasticsearchZonedDateTimeBridge@1bec1730]
        at 

Вот тесты, состоящие из двух блоков, которые я пробовал, где я могу воспроизвести проблему.

Если я создаю зонированное время даты ZoneId.of("UTC"), то это хорошо с elasti c мостом поиска

@Test
public void testObjectToString_withZoneId() {
    Date date = new Date();
    ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("UTC"));
    try {
        //this is good
          ElasticsearchZonedDateTimeBridge.INSTANCE.objectToString(zonedDateTime);
    } catch (DateTimeException e) {
        Assert.fail(e.getMessage());
    }
}

Но это не с кодом ниже

@Test
public void testObjectToString_withZonedOffset() {
    Date date = new Date();
    ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
    try {
        //this throws exception
          ElasticsearchZonedDateTimeBridge.INSTANCE.objectToString(zonedDateTime);
    } catch (DateTimeException e) {
        // Unable to extract value: class java.time.ZonedDateTime
        Assert.fail(e.getMessage());
    }
}

Версии Hibernate, которые я использую:

hibernate-search-elasticsearch, hibernate-search-orm = 5.11.4.Final

Вот моя полная трассировка стека

Caused by: org.hibernate.search.bridge.BridgeException: Exception while calling bridge#set
        entity class: com.x.x.x.x.Book
        entity property path: expectedDepartureTime
        document field name: expectedDepartureTime
        field bridge: TwoWayString2FieldBridgeAdaptor [stringBridge=org.hibernate.search.elasticsearch.bridge.builtin.time.impl.ElasticsearchZonedDateTimeBridge@1bec1730]
        at org.hibernate.search.bridge.util.impl.ContextualExceptionBridgeHelper.buildBridgeException(ContextualExceptionBridgeHelper.java:104) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.bridge.util.impl.ContextualExceptionBridgeHelper$OneWayConversionContextImpl.set(ContextualExceptionBridgeHelper.java:138) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForProperties(DocumentBuilderIndexedEntity.java:669) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:466) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.getDocument(DocumentBuilderIndexedEntity.java:402) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.createUpdateWork(DocumentBuilderIndexedEntity.java:312) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        ....
        ... 151 more
    Caused by: java.time.DateTimeException: Unable to extract value: class java.time.ZonedDateTime
        at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:282) ~[?:1.8.0_222]
        at java.time.format.DateTimeFormatterBuilder$ZoneIdPrinterParser.format(DateTimeFormatterBuilder.java:3787) ~[?:1.8.0_222]
        at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2190) ~[?:1.8.0_222]
        at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746) ~[?:1.8.0_222]
        at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720) ~[?:1.8.0_222]
        at org.hibernate.search.elasticsearch.bridge.builtin.time.impl.ElasticsearchTemporalAccessorStringBridge.format(ElasticsearchTemporalAccessorStringBridge.java:75) ~[hibernate-search-elasticsearch-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.elasticsearch.bridge.builtin.time.impl.ElasticsearchTemporalAccessorStringBridge.objectToString(ElasticsearchTemporalAccessorStringBridge.java:56) ~[hibernate-search-elasticsearch-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.bridge.util.impl.String2FieldBridgeAdaptor.set(String2FieldBridgeAdaptor.java:31) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.bridge.util.impl.ContextualExceptionBridgeHelper$OneWayConversionContextImpl.set(ContextualExceptionBridgeHelper.java:135) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForProperties(DocumentBuilderIndexedEntity.java:669) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:466) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.getDocument(DocumentBuilderIndexedEntity.java:402) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.createUpdateWork(DocumentBuilderIndexedEntity.java:312) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.addWorkToQueue(DocumentBuilderIndexedEntity.java:254) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]
        at org.hibernate.search.engine.impl.WorkPlan$PerEntityWork.enqueueLuceneWork(WorkPlan.java:560) ~[hibernate-search-engine-5.11.3.Final.jar:5.11.3.Final]

1 Ответ

1 голос
/ 27 января 2020

A ZoneOffset - это ZoneId, поэтому этот код верен:

    ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);

Однако Hibernate Search использует очень специфический формат c при сериализации зонированных дат в JSON. Этот формат требует наличия фактического идентификатора региона (а не только смещения).

Это можно считать ошибкой, и вы можете открыть отчет об ошибке, но, боюсь, это не единственная проблема. Даже если бы эта проблема была исправлена ​​в Поиске 5, для успешного индексирования такого значения нам все равно нужно было бы зарегистрировать исправление для HSEARCH-3548 , которое, насколько я понимаю, требует обратно несовместимых изменений в отображение Elasticsearch, сгенерированное поиском Hibernate. Поэтому я не уверен, что это можно исправить в 5.11.

Поддержка Elasticsearch в Hibernate Search 5 является экспериментальной. Если вы можете, вам будет гораздо удобнее перейти на Hibernate Search 6 (все еще в бета-версии), который обеспечивает первоклассную поддержку Elasticsearch 5.6 до 7.x, и который фактически имеет тест для вашей конкретной проблемы c ( и работает правильно). Однако API в Hibernate Search 6 отличаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...