繁体   English   中英

在联结表中使用复合主键时,Hibernate 未正确映射 object(“类型错误值”异常)

[英]Hibernate is not mapping object correctly ("Bad value for type" exception) when using compound primary keys in a junction table

我收到异常ohejsSqlExceptionHelper | Bad value for type int: 9dac4fd2-a04c-4be7-976b-d880a43ea25a ohejsSqlExceptionHelper | Bad value for type int: 9dac4fd2-a04c-4be7-976b-d880a43ea25a 好像是想在这里的一个Integer字段中放一个UUID。

我有下表,诚然它们在复合键方面有点复杂:

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
);

在我的 model 中,我有Event class,它非常简单。 ConditionSet class 有一个匹配数据库结构的复合主键,如下:

@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 值(最后的跟踪行),但在下一步(对于 Integer)它仍然尝试使用 UUID 而不是 Integer。

我在这里做错了什么吗?

我认为您不需要@JoinColumns并且它弄乱了哪个 id 列映射到ConditionSetEventId中的哪个 id 字段

    @Entity
    public class ConditionSetEvent {

      @EmbeddedId
      private ConditionSetEventId id;

      @ManyToOne(fetch = FetchType.LAZY)
      @OnDelete(action = OnDeleteAction.CASCADE)
      @MapsId("conditionSetId")
      private ConditionSet conditionSet;
      ....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM