簡體   English   中英

Hibernate OneToOne 在 PK 之間具有惰性行為

[英]Hibernate OneToOne between PK's with lazy behaviour

我正在嘗試使用 Hibernate 5.3.13.Final 和 Wildfly 18 下的注釋來實現一個名為MyEntity的實體以及另一個名為MyEntityInfo的實體。

這個想法是讓MyEntity存儲一些經常請求的字段,而MyEntityInfo存儲一些很少請求的字段。 兩者共享相同的主鍵,稱為 SID (Long),並且從 Info 的 SID 到 Entity 的 SID 有一個 FK。 可以有沒有信息的實體。

通常你不需要額外的信息。 例如,當我像這樣查詢我的實體時,我不希望獲取信息實體:

MyEntityImpl entity = em.find(MyEntityImpl.class, 1L);

但是,當我運行這段代碼時,我發現有第二個查詢,沿着主要的查詢實體獲取 Info 實體,就像在EAGER行為中一樣。

我正在使用@OneToOne映射關系。 我嘗試了幾種 FetchType 、 optionalFetchType@LazyToOne ,但到目前為止都沒有成功。

這是 MyEntity 和 MyEntityInfo 類的代碼(刪除了額外的 getter 和 setter):

MyEntity(ID 生成器是一個自定義序列生成器):

@Entity
@Table(name = MyEntityImpl.TABLE_NAME)
public class MyEntityImpl {

    public static final String TABLE_NAME = "TMP_MY_ENTITY";

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "GEN_" +
            TABLE_NAME)
    @GenericGenerator(name = "GEN_" +
            TABLE_NAME, strategy = CoreIdGenerator.ID_GENERATOR, parameters = {
                    @Parameter(name = "tableName", value = TABLE_NAME) })
    @Column(name = "sid", nullable = false, unique = true)
    private Long               sid;

    @OneToOne(mappedBy = "myEntity", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
    @LazyToOne(LazyToOneOption.NO_PROXY)
    private MyEntityInfoImpl   info;

    @Column
    private String             field;

我的實體信息:

@Entity
@Table(name = MyEntityInfoImpl.TABLE_NAME)
public class MyEntityInfoImpl {
    public static final String TABLE_NAME = "TMP_MY_ENTITY_INFO";

    @Id
    @Column(name = "SID", nullable = false, unique = true)
    private Long               sid;

    @OneToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name = "SID", referencedColumnName = "SID", insertable = false, updatable = false, nullable = false)
    private MyEntityImpl       myEntity;

    @Column(name = "INFO_FIELD")
    private String             infoField;

我已經嘗試過這個解決方案,但正如我所說,它對我不起作用:

Hibernate 延遲加載以實現反向一對一解決方法 - 這是如何工作的?

我已經設法使用@OneToMany並手動管理數據做了一些類似的事情,但這不是我想做的。 然而,關於是否可以使用@OneToOne或正確的設計模式來實現這一點的另一種替代方案和信息也受到歡迎。

PS:為 SQL 服務器創建數據庫表,如果您想嘗試:

create table TMP_MY_ENTITY (SID NUMERIC(19,0) NOT NULL, FIELD VARCHAR(100));
go
ALTER TABLE TMP_MY_ENTITY ADD CONSTRAINT PK_TMP_MY_ENTITY PRIMARY KEY CLUSTERED (SID);
go

create table TMP_MY_ENTITY_INFO (SID NUMERIC(19,0) NOT NULL, INFO_FIELD VARCHAR(100));
go
ALTER TABLE TMP_MY_ENTITY_INFO ADD CONSTRAINT PK_TMP_MY_ENTITY_INFO PRIMARY KEY CLUSTERED (SID);
go

CREATE SEQUENCE SEQ_TMP_MY_ENTITY START WITH 1 INCREMENT BY 1 MINVALUE 1 CACHE 20;

alter table TMP_MY_ENTITY_INFO add constraint FK_TMP_MY_ENT_INFO_MY_ENT FOREIGN KEY (SID) references TMP_MY_ENTITY(SID);
go

insert into TMP_MY_ENTITY(SID, FIELD) VALUES (NEXT VALUE FOR SEQ_TMP_MY_ENTITY, 'Field 1');
insert into TMP_MY_ENTITY_INFO(SID, INFO_FIELD) VALUES ((SELECT MAX(SID) FROM TMP_MY_ENTITY), 'Info 1');

insert into TMP_MY_ENTITY(SID, FIELD) VALUES (NEXT VALUE FOR SEQ_TMP_MY_ENTITY, 'Field 2');
insert into TMP_MY_ENTITY_INFO(SID, INFO_FIELD) VALUES ((SELECT MAX(SID) FROM TMP_MY_ENTITY), 'Info 2');

insert into TMP_MY_ENTITY(SID, FIELD) VALUES (NEXT VALUE FOR SEQ_TMP_MY_ENTITY, 'Field 3 no info');

-- DELETE ALL

drop table TMP_MY_ENTITY_INFO;
drop table TMP_MY_ENTITY;
drop sequence SEQ_TMP_MY_ENTITY;

在關注@SternK 鏈接並升級到 Wildfly 19 和 Hibernate 5.4.14 之后,它終於可以使用@MapsId工作了。

要使用的正確映射是這樣的:

我的實體:

public class MyEntityImpl {

    @OneToOne(mappedBy = "myEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, optional = true)
    @JoinColumn(name = "SID")
    private MyEntityInfoImpl   info;

我的實體信息:

public class MyEntityInfoImpl {

    @OneToOne(fetch = FetchType.EAGER, optional = false)
    @MapsId
    @JoinColumn(name = "SID", referencedColumnName = "SID", insertable = false, updatable = false, nullable = false)
    private MyEntityImpl       myEntity;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM