Hibernate多对多3个表

时间:2014-07-20 17:02:36

标签: java sql hibernate


我在hibernate中遇到了很多mamy关系的问题。
这个想法是:我有一个Employee(pracownik)表,一个grapfic(grafik)表和一个shift(detale zmiany)表。现在我想要一张表,我可以检查一位员工的工作情况,例如。从01.01-07.01上午6点到下午2点。
因此,该表将包含像idpracownika(employeeid),idgrafiku(graphicid)和idzmiany(shiftid)这样的列。
我所做的是:

Pracownik.class

@Entity(name = "pracownik")
@Inheritance(strategy = InheritanceType.JOINED)
@Proxy(lazy = false)
public class Pracownik

@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
@JoinTable(name = "grafikpracownika", joinColumns = { @JoinColumn(name = "idosoby") }, 
inverseJoinColumns = { @JoinColumn(name = "idgrafiku") })
private List<Grafik> grafiki = new ArrayList<>();

@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
@JoinTable(name = "grafikpracownika", joinColumns = { @JoinColumn(name = "idosoby") }, 
inverseJoinColumns = { @JoinColumn(name = "idzmiany") })
private List<DetaleZmiany> detaleZmiany = new ArrayList<>();

Grafik.class

@Entity(name = "grafik")
@Proxy(lazy = false)
public class Grafik

@ManyToMany(mappedBy = "grafiki", cascade = { CascadeType.ALL })
private List<Pracownik> pracownik = new ArrayList<>();

DataleZmiany

@Entity (name = "detalezmiany")
@Proxy(lazy = false)
public class DetaleZmiany {

@ManyToMany (mappedBy = "detaleZmiany",cascade = { CascadeType.ALL })
private List <Pracownik> pracownik  = new ArrayList<>();

现在我在pracownik,grafik和detale zmiany表中有一些记录,所以现在我只需要&#34;结合&#34;它在一起。

    public static void main(String[] args) {

    PracownikService pracowniks = new PracownikService();
    GrafikDao grafikdao = new GrafikDao();
    DetaleZmianyDao dz = new DetaleZmianyDao();

    Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();

    Pracownik emp1 = pracowniks.getPracownikById(19);
    Pracownik emp2 = pracowniks.getPracownikById(20);

    Grafik g1 = grafikdao.getGrafikById(1);
    Grafik g2 = grafikdao.getGrafikById(2);

    DetaleZmiany d1 = dz.getDetaleById(1);
    DetaleZmiany d2 = dz.getDetaleById(2);

    emp1.getGrafiki().add(g1);
    emp1.getGrafiki().add(g2);

    emp1.getDetaleZmiany().add(d1);
    emp1.getDetaleZmiany().add(d2);

    emp2.getGrafiki().add(g2);
    emp2.getDetaleZmiany().add(d1);

    pracowniks.updatePracownik(emp1);
    pracowniks.updatePracownik(emp2);

}

尝试使用此代码我会收到"null value in column "idgrafiku" violates not-null constraint"之类的例外情况 我还检查了sql插件,它看起来像:

    insert 
into
    grafikpracownika
    (idosoby, idzmiany) 
values
    (?, ?)

因此插入会跳过idgrafiku。为什么? 你能帮忙吗? 我尝试了几种选择但没有成功......

1 个答案:

答案 0 :(得分:0)

您想在1个关联表中映射2个关系(pracownik&lt; - &gt; grafik,pracownik&lt; - &gt; zmiany)。这很好,但使用ORM(如Hibernate)实现它并不是那么简单。

Hibernate无法(根据您的定义)知道两个关系属于同一个关联,因此将它们视为2个不同的关联。因此,它尝试在关联表(grafikpracownika)中插入2行,这两行中的每一行在其中一列中都为null。这就是你得到空约束违规的原因。

您需要做的是添加一个代表该关联的新实体。现在,我并不真正理解&#34; grapfic&#34;的含义,所以我只给它一个通用名称&#34; Assoc&#34;。它显然有3个属性:idosoby,idgrafiku,idzmiany。现在将您的Pracownik链接到Assoc。

要解决员工工作时找到时间间隔的问题,您可以简单地遍历Pracownik的所有Assocs并过滤您感兴趣的那些。但是如果您的数据库将包含许多条目,为了提高效率我强烈建议删除FetchType.EAGER修饰符并改为使用默认的延迟加载。然后使用HQL将过滤留到数据库是有意义的。