Спящий режим — невозможно вставить новую запись при использовании составного первичного ключа (@idClass), учитывая сохранение его автоматически сгенерированного атрибута.

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

Атрибуты @IdClass:

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

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

Чтобы ВСТАВИТЬ новую запись, сохраняя значение «id» и увеличивая «версию».

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

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

Желаемая новая запись (НЕ ОБНОВЛЕНА, речь о новой) - {id:1, version: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:

введите здесь описание изображения

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

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

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


person Caio Dornelles Antunes    schedule 03.05.2019    source источник


Ответы (1)


Задача решена!

Проблема была в моей реализации 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);
    }

}
person Caio Dornelles Antunes    schedule 03.05.2019