Hibernate ManyToMany产生了笛卡尔积

时间:2014-07-21 02:51:24

标签: java hibernate jpa

我是hibernate / JPA的新手,对这个noob问题道歉。我跟随实体的关系

  • 经理与工人有很多关系
  • 工人与任务有很多关系

以下是ERD

enter image description here

以下是我的java课程

@Entity
@table(name="manager")
public class Manager {

private long id;

private String name;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "manager_worker", joinColumns = { @JoinColumn(name = "manager_id") },
            inverseJoinColumns = { @JoinColumn(name = "worker_id") })
private ArrayList<Worker> workers = new ArrayList<Worker>();

 // ......getter setter
}

@Entity
@Table(name = "worker")
public class Worker {

@Id
private long id;

private String name;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "worker_task", joinColumns = { @JoinColumn(name = "worker_id") },
            inverseJoinColumns = { @JoinColumn(name = "task_id") })
private ArrayList<Task> tasks = new ArrayList<Task>();
  ...........................
}

@Entity
@Table(name = "task")
public class Task {

@Id
private long id;

private String title;
          .................
}

我有以下数据:

  • 经理M1有工人W1和W2
  • W1具有任务TW1,TW2,TW3
  • W2有任务TW2和TW2

当我获得Id M1的Manager对象时,结果具有Worker和Task的笛卡尔积,即W1数据重复3次,W2数据重复2次,即Manager.worker数组列表有5个worker对象而不是2

要加载我正在使用Session.get()方法的数据

public E find(final K key) {
    return (E) currentSession().get(daoType, key);
}

任何人都可以告诉我如何解决这个问题并指出我在这种情况下应该使用的任何最佳做法。

由于

2 个答案:

答案 0 :(得分:3)

这是因为两个@ManyToMany关系都是急切加载的。

这将导致所有三个表的外连接。此查询的结果是五行,其中W1出现三次,W2出现两次。到目前为止,一切都是正确的。

但是出于某种原因,Hibernate只是将所有工作者都放在集合中,即使它们是重复的。它甚至在FAQ中描述。

有多种方法可以解决此问题:

  • 将其中一个关系更改为延迟加载
  • 使用Set代替List(你不应该使用ArrayList作为变量类型,尤其是在使用Hibernate时)
  • @Fetch(FetchMode.SELECT)用于tasks

答案 1 :(得分:2)

targetEntity关系中的@ManyToMany在哪里?

你应该有类似的东西:

@ManyToMany(targetEntity = Task.class)
@JoinTable(name = "worker_task", joinColumns = { @JoinColumn(name = "worker_id") },
            inverseJoinColumns = { @JoinColumn(name = "task_id") })
private ArrayList<Task> tasks = new ArrayList<Task>();

我建议你改为@OneToMany@ManyToOne关系。这个概念与数据库设计更加兼容,当人们查看ERD时更容易理解。所以Manager与Manager_Worker有一对多的关系,因此manager_worker与经理有多对一的关系。对其他实体保持不变。