Hibernate - Невозможно вставить новую запись при использовании составного первичного ключа (@idClass), учитывая его автоматически сгенерированный атрибут - PullRequest
0 голосов
/ 03 мая 2019

Я постараюсь выразиться проще.У меня есть таблица с составным первичным ключом, состоящим из двух атрибутов Long, обернутых аннотированным классом @IdClass.

@ Атрибуты IdClass:

public class MyPK implements Serializable {
    private Long id;
    private Long version;
} // + hashCode, constructors, etc.

Что я не могу сделать:

Чтобы вставить новую запись, покасохранение значения «id» и увеличение «version».

Пример сценария:

Существующая запись - {id: 1, версия: 1}

Желаемая новая запись (НЕ ОБНОВЛЕНО, говорим о новой) - {id: 1, версия: 2}

Что я сделал:

СначалаЯ попытался увеличить версию, сохранив генератор последовательности, который использовал.Ниже показано, как аннотировался идентификатор:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSequence")
@SequenceGenerator(name = "idSequence", sequenceName = "SQ_ID", allocationSize = 1)
@Column(name = "ID", nullable = false, updatable = false)
private Long id;

Вышеуказанное привело к переопределению предоставленного идентификатора с помощью nextVal последовательности, поэтому для меня не было никакой сделки.

Так что мой второй подход состоял в том, чтобы поигратьнаследование и внутренние классы Hibernate, чего я всегда стараюсь избегать:

public class MySequenceStyleIdGenerator extends SequenceStyleGenerator {

    @Override
    public Serializable generate(SessionImplementor session, Object object){
        Serializable id = session.getEntityPersister(null, object)
                .getClassMetadata().getIdentifier(object, session);

        return id != null && ((MyPK)id).getId() != null
                ? id : super.generate(session, object);
    }

}

И внесение изменений в класс сущностей по мере необходимости:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "providedIdOrSequence")
@GenericGenerator(
        name="providedIdOrSequence",
        strategy="{package}.MySequenceStyleIdGenerator",
        parameters = @org.hibernate.annotations.Parameter(
                name = "sequence_name",
                value = "SQ_ID"
        )
)
@Column(name = "ID", nullable = false, updatable = false)
private Long id;

Это, с другой стороны, возвращает nextValв идентификатор ТОЛЬКО когда он нулевой, что я и хотел.Затем проблема переходит на что-то более темное и глубокое в библиотеке, как будто она пытается присвоить id (Long) самому типу PK вместо его атрибута Long:

enter image description here

java.lang.IllegalArgumentException: Невозможно установить для поля java.lang.Long {package} .CotacaoPK.idCotacao значение {package} .CotacaoPK

Если оба атрибута PK(идентификатор и версия) остаются без изменений, тогда я не получаю ошибки.

Есть идеи?Я уже потратил на это разумное количество часов ... спасибо.

1 Ответ

0 голосов
/ 03 мая 2019

Проблема решена!

Проблема была в моей реализации SequenceStyleGenerator. super.generate (...) возвращает Long, но я возвращал id в качестве объекта MyPK для переноса. Таким образом, решение будет:

public class MySequenceStyleIdGenerator extends SequenceStyleGenerator {

@Override
public Serializable generate(SessionImplementor session, Object object){
        Serializable id = session.getEntityPersister(null, object)
                .getClassMetadata().getIdentifier(object, session);

        return id != null && ((MyPK)id).getId() != null
                ? ((MyPK)id).getId() : super.generate(session, object);
    }

}
...