Hibernate生成额外的sql

时间:2012-06-27 09:22:35

标签: hibernate join fetch one-to-one

我有两个实体:儿童。并且它们之间存在 @OneToOne 关系。

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

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

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

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

你可能会尝试不同的fetchtype;

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

但是,正如JB Nizet已经解释的那样,潜在的问题是存储在CHILD_ID字段中的虚构标识符。

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