Hibernate多对多连接条件

时间:2012-10-31 08:06:09

标签: java sql hibernate many-to-many hql

+-------+    +--------------|     +-------+
| BOY   |    | BOY_GIRL     |     | GIRL  | 
+-------+    +--------------|     +-------+
| id    |    | id           |     | id    |
| name  |    | boy_id       |     | name  |
| birth |    | girl_id      |     | birth |
+-------+    | start_dating |     +-------+
             +--------------|

START_DATING的类型为TIMESTAMPDATE

我有两个豆子男孩和女孩有多对多的关系

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "BOY_GIRL", joinColumns = {@JoinColumn(name = "BOY_ID")}, inverseJoinColumns = {@JoinColumn(name = "GIRL_ID")})
public Set<Girl> getGirls() {
    return girls;
}

现在,我如何使用HQL选择查询,如果我想让列表女孩有条件:

where boy_id = (some_boy_id) and START_DATING > (some_timestamp)

4 个答案:

答案 0 :(得分:4)

我认为你的实体模型不正确,你需要一个代表关系属性的第三个实体,你应该将男孩和女孩同时映射到该实体。 否则,无法在您的情况下将starting_date指定为关系属性,作为查询中的条件。 查看this link,您可以找到有关如何使用其他属性映射连接表的详细说明。

答案 1 :(得分:4)

我认为你必须创建一个BoyGirl类,因为表BOY_GIRL不是一个简单的多对多表(如果是,那么列必须只有boy_idgirl_id)。那么你应该做的是创建BoyGirl类,然后将BOY映射到BOY_GIRL一对多,并将GIRL映射到BOY_GIRL,其中一个 - 对多

表关系

+-------+               +--------------+               +-------+
| BOY   |               | BOY_GIRL     |               | GIRL  | 
+-------+               +--------------|               +-------+
| id    | 0..* --- 1..1 | id           | 1..1 --- 0..* | id    |
| name  |               | boy_id       |               | name  |
| birth |               | girl_id      |               | birth |
+-------+               | start_dating |               +-------+
                        +--------------+

java类

public class BoyGirl {
  private long id;
  private Boy boy;
  private Girl girl;
  private Date startDating;
}

public class Boy {
  //other attributes omitted
  private Set<BoyGirl> boyGirls;
}

public class Girl {
  //other attributes omitted
  private Set<BoyGirl> boyGirls;
}

您需要的选择查询

// I'm using criteria here, but it will have the same result as your HQL

public List getGirls(Boy boy, Date startDating) {
  Criteria c = sessionFactory.getCurrentSession().createCriteria(BoyGirl.class);
  c.add(Restrictions.eq("boy.id", boy.getId());
  c.add(Restrictions.lt("startDating", startDating);

  List<BoyGirl> boyGirls = (List<BoyGirl>) c.list();
  // at this point you have lazily fetch girl attributes
  // if you need the girl  attributes to be initialized uncomment line below
  // for (BoyGirl boyGirl : boyGirls) Hibernate.initialize(boyGirl.getGirl());

  return boyGirls;
}

答案 2 :(得分:1)

由于中间表BOY_GIRL有一些额外的属性(start_dating),您需要在域模型中为它​​创建另一个中间实体,例如:

@Table(name="BOY_GIRL")
class Relationship {

  @Id
  long id;

  @ManyToOne
  Boy boy;

  @ManyToOne;
  Girl girl;

  @Column
  Date startDating;
}

答案 3 :(得分:0)

我认为将约会信息直接保存在联接表中并不是很好(因为这样做的目的应该只是关联一个男孩和一个女孩)。

但是,如果您真的想保留当前的结构并使用HQL解决它,那么您应该可以执行类似

的操作
SELECT g FROM GIRL g, BOY_GIRL bg 
WHERE bg.start_dating = :revelantdate 
    AND bg.boy_id = :boyid
    AND g.id = bg.girl_id