0

我有两个实体:ParentChild。它们之间存在@OneToOne关系。

我有以下查询:from Parent p left join fetch p.child

如果 Parent 中有一行不存在子键(例如 -1),则休眠会为每种情况发出额外的查询。

Hibernate: 
    select
        parent0_.PARENT_ID as PARENT1_2_0_,
        child1_.CHILD_ID as CHILD1_3_1_,
        parent0_.CHILD_ID as CHILD2_2_0_,
        child1_.NAME as NAME3_1_ 
    from
        PARENT parent0_ 
    left outer join
        CHILD child1_ 
            on parent0_.CHILD_ID=child1_.CHILD_ID
Hibernate: 
    select
        child0_.CHILD_ID as CHILD1_3_0_,
        child0_.NAME as NAME3_0_ 
    from
        CHILD child0_ 
    where
        child0_.CHILD_ID=?

这是代码:

@Entity
@Table(name = "PARENT")
public class Parent {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PARENT_ID", nullable = false)
    private int id;

    @OneToOne(optional = true)
    @JoinColumn(name = "CHILD_ID")
    @NotFound(action = NotFoundAction.IGNORE)
    private Child child;
}

@Entity
@Table(name="CHILD")
public class Child {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "CHILD_ID", nullable = false)
    private int id;

    @Column(name = "NAME")
    private String name;
}

为什么会这样?如何防止这个额外的sql?

这是数据库生成的代码:

create table PARENT(
PARENT_ID INTEGER GENERATED ALWAYS AS IDENTITY,
CHILD_ID  INTEGER, 
PRIMARY KEY (PARENT_ID)
);

create table CHILD(
CHILD_ID  INTEGER GENERATED ALWAYS AS IDENTITY,
NAME VARCHAR(100) NOT NULL,
PRIMARY KEY (CHILD_ID)
);

insert into PARENT(CHILD_ID) values(-1);
4

2 回答 2

0

您可能会尝试不同的 fetchtype;

@OneToOne(optional = true, fetch = FetchType.EAGER)
private Child child;

但是,就像 JB Nizet 已经解释的那样,根本问题是存储在 CHILD_ID 字段中的虚构标识符。

另一种策略是反转关系,通过在父类的@OneToOne 注释中添加 mappedBy 属性,并在子类中添加对父类的引用,或者仅在子类中设置父类。

于 2012-06-27T11:55:15.290 回答
0

正确设计数据库,不要在PARENT.CHILD_ID列中存储不存在的子 ID。如果父级没有子级,则在此列中存储 NULL,并为该列创建外键约束以确保该列始终包含 NULL 或有效的子级 ID。

这将允许您@NotFound从映射中删除注释,并将删除附加查询。实际上,当 Hibernate 执行第一个查询时,它会得到 -1 作为子 ID。但是由于无法知道 -1 是否是有效的子 ID,它必须执行附加查询来确定子是否存在(因此应该在父级中初始化)或不存在(因此应该在父级中设置为 null)。

于 2012-06-27T09:48:47.373 回答