SpringBoot JPA 2.1 Converter игнорирует convertToDatabaseColumn - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть следующий конвертер

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class ImportedReasonConverter implements AttributeConverter<ImportedReason, String> {
    @Override
    public String convertToDatabaseColumn(final ImportedReason pImportedReason) {
        return pImportedReason.getValue();
    }

    @Override
    public ImportedReason convertToEntityAttribute(final String pImportedReason) {
        return ImportedReason.of(pImportedReason);
    }
}

, который используется такой сущностью, как

@Entity
@Table(
        name = "IMPORT_RECORD"
)
public class ImportRecordEntity implements Serializable {

    private static final long serialVersionUID = 2483327758356663412L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private UUID id;

    @Column(name = "importedReason")
    private ImportedReason importedReason;

    public ImportedReason getImportedReason() {
        return importedReason;
    }

    public void setImportedReason(final ImportedReason importedReason) {
        this.importedReason = importedReason;
    }

{...}
}

При запуске приложения Hibernate создает таблицу, используя правильный столбец тип (здесь: VARCHAR). Удаление параметра autoApply = true приводит к ошибке запуска - поэтому сам конвертер распознается.

Но: при сохранении сущности со значением, установленным на importReason, я получаю

Caused by: java.io.NotSerializableException: ImportedReason
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
    at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
    at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
    at org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:115)
    ... 43 more

Попробуйте отладить мой конвертер, метод ImportedReasonConverter.convertToDatabaseColumn (ImportedReason) не вызывается. Поэтому Hibernate не пытается записать значение типа String, а типа ImportedReason.

Есть идеи, почему конвертер не используется должным образом? Я пробовал это с Java 8 + 11 и Spring 2.1.5.RELEASE + 2.1.9.RELEASE (более ранние версии использовались для работы с другим проектом). Я также пробовал это с некоторыми другими конвертерами (например, внутренний тип -> LocalDateTime), но у меня также есть та же проблема.

Большое спасибо. Stefan

Ответы [ 2 ]

0 голосов
/ 25 февраля 2020

О, боже ... это soo dump ...

Я забыл, что это отображение @OneToOne

Мои сущности необходимо настроить следующим образом:

@Entity
@Table(
        name = "PROVIDER_PORTFOLIO"
)
public class PortfolioEntity implements Serializable {

    private static final long serialVersionUID = 3632725596750538287L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private UUID id;

    @OneToOne
    @JoinColumn(
            name = "IMPORT_RECORD_ID"
    )
    private ImportRecordEntity importRecord;
[...]
}

@Entity
@Table(
        name = "IMPORT_RECORD"
)
public class ImportRecordEntity implements Serializable {

    private static final long serialVersionUID = 2483327758356663412L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private UUID id;

    @Column(name = "importedReason")
    private ImportedReason importedReason;
[...]
}

ну ... простите за путаницу, должен был просто перестать работать;)

Стефан

0 голосов
/ 25 февраля 2020

Обновление: Дальнейшие исследования показали, что сущность, которая сохраняется, полностью проанализирована и ее преобразователи используются должным образом. Но: , если эта сущность использует еще какую-то другую сущность в качестве ссылки, которая, в свою очередь, использует типы, которые должны быть преобразованы с использованием этих преобразователей: именно тогда она видит значения, но не использует преобразователь (по какой-то причине).

Итак, мой ImportRecordEntity сверху используется в следующем PortfolioEntity, который я на самом деле пытаюсь сохранить. Сохранение ImportRecordEntity работает без проблем. Затем я устанавливаю этот экземпляр ImportRecordEntity (возвращенный из метода save) на экземпляр PortfolioEntity и сохраняю его. Но затем происходит сбой Hibernate, потому что кажется, что он проанализировал PortfolioEntity, но не ImportRecordEntity, который содержит ImportedReason - поэтому он не знает о ImportedReasonConverter (см. Org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrRepersister (Object, EntityKey, Entity, EntityKey, Entity) boolean, Object, EventSource, boolean) - AbstractSaveEventListener. java: 122 типа переменных).


@Entity
@Table(
        name = "PORTFOLIO"
)
public class PortfolioEntity implements Serializable {

    private static final long serialVersionUID = 3632725596750538287L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private UUID id;

    @Column(name = "IMPORT_RECORD")
    private ImportRecordEntity importRecord;

{...}
}
...