Hibernate неправильно отображает объект (исключение «Недопустимое значение для типа») при использовании составных первичных ключей в таблице соединений. - PullRequest
3 голосов
/ 03 августа 2020

Я получаю исключение o.h.e.j.s.SqlExceptionHelper | Bad value for type int : 9dac4fd2-a04c-4be7-976b-d880a43ea25a. Кажется, здесь нужно поместить UUID в поле Integer.

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

CREATE TABLE public.event (
    id uuid NOT NULL,
    ...
    CONSTRAINT event_pkey PRIMARY KEY (id)
);

CREATE TABLE public.condition_set (
    api_id uuid NOT NULL,
    version integer NOT NULL,
    ...,
    CONSTRAINT condition_set_pkey PRIMARY KEY (api_id, version)
);

CREATE TABLE public.condition_set_event (
    condition_set_api_id uuid NOT NULL,
    condition_set_version integer NOT NULL,
    event_id uuid NOT NULL,
    CONSTRAINT condition_set_event_pkey PRIMARY KEY (condition_set_api_id, condition_set_version, event_id),
    CONSTRAINT fk_condition_set FOREIGN KEY (condition_set_api_id, condition_set_version) REFERENCES public.condition_set(api_id, version) ON DELETE CASCADE,
    CONSTRAINT fk_event FOREIGN KEY (event_id) REFERENCES public.event(id) ON DELETE CASCADE
);

В моей модели У меня есть класс Event, который довольно прост. Класс ConditionSet имеет составной первичный ключ, соответствующий структуре базы данных, а именно:

@Entity
public class ConditionSet {

    @EmbeddedId
    private ConditionSetId id;
}

, который выглядит так:

@Embeddable
public class ConditionSetId implements Serializable {

    private static final long serialVersionUID = 8110138933878596476L;

    private UUID apiId;
    private Integer version;

}

Сложная часть - это таблица соединений ConditionSetEvent который ТАКЖЕ состоит из составного ключа, один из которых является составным ключом ConditionSet

@Entity
public class ConditionSetEvent {

    @EmbeddedId
    private ConditionSetEventId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @MapsId("conditionSetId")
    @JoinColumns(foreignKey = @ForeignKey(name = "fk_condition_set"), value = {
        @JoinColumn(nullable = false, name = "conditionSetApiId"),
        @JoinColumn(nullable = false, name = "conditionSetVersion")
    })
    private ConditionSet conditionSet;

    @ManyToOne(fetch = FetchType.LAZY)
    @OnDelete(action = OnDeleteAction.CASCADE)
    @MapsId("eventId")
    @JoinColumn(foreignKey = @ForeignKey(name = "fk_event"))
    private Event event;

    public ConditionSetEvent(ConditionSet conditionSet, Event event) {
        this.conditionSet = conditionSet;
        this.event = event;
        this.id = new ConditionSetEventId(conditionSet.getId(), event.getId());
    }
}

с его EmbeddedId:

@Embeddable
public class ConditionSetEventId implements Serializable {

    private static final long serialVersionUID = -6269791751266804667L;

    private ConditionSetId conditionSetId;
    private UUID eventId;
}

Однако, если я попытаюсь запросить это соединение таблица с этим методом репозитория:

public interface ConditionSetEventRepository extends JpaRepository<ConditionSetEvent, ConditionSetEventId> {

    @Query("select cse from ConditionSetEvent cse where cse.id.eventId = :eventId")
    List<ConditionSetEvent> findByEventId(UUID eventId);
}

, тогда я получаю сообщение об ошибке, как указано выше (где uuid в исключении является допустимым ConditionSet.apiId, но каким-то образом кажется, что он используется повторно.

С ведением журнала трассировки:

DEBUG | org.hibernate.SQL | select conditions0_.condition_set_api_id as conditio0_8_, conditions0_.event_id as event_id1_8_, conditions0_.condition_set_api_id as conditio2_8_, conditions0_.condition_set_version as conditio3_8_ from condition_set_event conditions0_ where conditions0_.event_id=?
TRACE | o.h.t.d.sql.BasicBinder | binding parameter [1] as [OTHER] - [be1ec45d-6533-4e77-98b7-f9a357cda052]
TRACE | o.h.t.d.s.BasicExtractor | extracted value ([conditio0_8_] : [OTHER]) - [9dac4fd2-a04c-4be7-976b-d880a43ea25a]
WARN | o.h.e.j.s.SqlExceptionHelper | SQL Error: 0, SQLState: 22003
ERROR | o.h.e.j.s.SqlExceptionHelper | Bad value for type int : 9dac4fd2-a04c-4be7-976b-d880a43ea25a

Таким образом, ему удается сначала извлечь это значение UUID (последняя строка трассировки), но на следующем шаге (для целого числа) он все еще пытается использовать UUID вместо Integer.

Я что-то здесь делаю не так?

1 Ответ

1 голос
/ 04 августа 2020

Я не думаю, что вам нужен @JoinColumns, и он портит, какой столбец идентификатора сопоставляется с каким полем идентификатора в ConditionSetEventId

    @Entity
    public class ConditionSetEvent {

      @EmbeddedId
      private ConditionSetEventId id;

      @ManyToOne(fetch = FetchType.LAZY)
      @OnDelete(action = OnDeleteAction.CASCADE)
      @MapsId("conditionSetId")
      private ConditionSet conditionSet;
      ....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...