Hibernate FechType.LAZY不适用于复合@ManyToOne关系

时间:2013-02-06 15:01:57

标签: hibernate jpa-2.0 composite-key

没有复合关系的@ManyToOne关系工作得很好:

@Entity
@Table
public class Telefoni{
    ... other fields not included for simplicity sake

    private DjecaRoditelja djecaRoditelja;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "IDDjeteta", referencedColumnName = "IDDjeteta")
    public DjecaRoditelja getDjecaRoditelja() {
        return this.djecaRoditelja;
    }

    public void setDjecaRoditelja(DjecaRoditelja djecaRoditelja) {
        this.djecaRoditelja = djecaRoditelja;
    }
}

...

// in some DAO method
tel = entityManager.find(Telefoni.class, primaryKey);

执行1个SQL查询,从Telefoni表中只获取一行,持续约10ms。

但是当使用复合@JoinColumns添加任何@ManyToOne关系时,延迟提取会停止工作:

@Entity
@Table
public class Telefoni{
    ... other fields not included for simplicity sake

    private KontaktOsobe kontaktOsobe;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "KORISNIK", referencedColumnName = "korisnik"),
            @JoinColumn(name = "PARTNER", referencedColumnName = "Partner"),
            @JoinColumn(name = "SifraKonOs", referencedColumnName = "SifraOsobe") })
    public KontaktOsobe getKontaktOsobe() {
        return this.kontaktOsobe;
    }

    public void setKontaktOsobe(KontaktOsobe kontaktOsobe) {
        this.kontaktOsobe = kontaktOsobe;
    }
}

...

// in some DAO method
tel = entityManager.find(Telefoni.class, primaryKey);   

执行37个SQL查询,急切地获取每个父实体和每个父节点的父节点,直到它解析所有关系。这持续约600ms。

我为我的实体添加一个额外的关系,性能提高了60倍......除了更改我的数据库模型之外,还有什么方法可以让懒惰的提取与复合关系一起工作吗?

编辑:

在更详细地研究这个问题之后,问题与复合关系无关,而是通过任何未超过JPA / Hibernate定义的主键的关系。

因此,如果我有一个带有标识列和自然唯一的表,以及通过其中一个相关的各种表 - 我必须决定哪一个不那么灾难性地被急切地取出并把另一个作为Hibernate的主键。

1 个答案:

答案 0 :(得分:0)

在相关表KontaktOsobe上,主键必须是@EmbeddedId,它由构成关系的组件组成。

@Entity
@Table
public class KontaktOsobe{
    private KontaktOsobePK pk;

    @EmbeddedId
    public KontaktOsobePK getPk() {
        return pk;
    }
    // ... 
}

@Embeddable
public class KontaktOsobePK implements Serializable {
    private static final long serialVersionUID = 1L;

    private String sifraOsobe;
    private String partner;
    private String korisnik;

    // getters, setters, equals and hashode methods go here...
}

如果同时你也有关系定位另一个字段(即自动增量标识字段),你必须决定哪个延迟提取将起作用...