简体   繁体   English

Hibernate多对多连接条件

[英]Hibernate many-to-many join with condition

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

START_DATING is type of TIMESTAMP or DATE START_DATINGTIMESTAMPDATE类型

I have two beans Boy and Girl with many-to-many relation 我有两个豆子男孩和女孩有多对多的关系

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

Now, how can I do select query with HQL, if I want to get the list girls with condition: 现在,我如何使用HQL选择查询,如果我想获得有条件的列表女孩:

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

I think your entity model is not correct, you need a third entity representing the relationship attribute and you should map both Boy and Girl as many to one to that entity. 我认为你的实体模型不正确,你需要一个代表关系属性的第三个实体,你应该将男孩和女孩同时映射到该实体。 Otherwise there is no way to specify the relationship attribute, in your case starting_date, as a condition in a query. 否则,无法在您的情况下将starting_date指定为关系属性,作为查询中的条件。 Look at this link , you can find a detailed explanation on how to map a join table with additional attributes. 查看此链接 ,您可以找到有关如何使用其他属性映射连接表的详细说明。

I think you have to create a BoyGirl class because table BOY_GIRL is not a simple many-to-many table (If it is, then the columns are has to be only boy_id and girl_id ). 我认为你必须创建一个BoyGirl类,因为表BOY_GIRL不是一个简单的多对多表(如果是,那么列必须只是boy_idgirl_id )。 So what you should do is create the BoyGirl class then map BOY to BOY_GIRL with one-to-many and also map GIRL to BOY_GIRL with one-to-many 那么你应该做的是创建BoyGirl类然后用BoyGirl映射BOYBOY_GIRL ,并用一对多映射GIRLBOY_GIRL

table relations 表关系

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

java classes 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;
}

The select query you need 您需要的选择查询

// 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;
}

As the intermediate table BOY_GIRL has some additional attributes ( start_dating ) you need to create another intermediate entity in your domain model for it, eg: 由于中间表BOY_GIRL具有一些额外的属性( start_dating ),您需要在域模型中为它​​创建另一个中间实体,例如:

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

  @Id
  long id;

  @ManyToOne
  Boy boy;

  @ManyToOne;
  Girl girl;

  @Column
  Date startDating;
}

I don't think its great to keep the dating information directly inside the join table (since the purpose of this should simply be to associate a boy and a girl). 我认为将约会信息直接保存在联接表中并不是很好(因为这样做的目的应该只是关联一个男孩和一个女孩)。

However, if you really want to keep your current structure, and solve it with HQL, you should be able to do something like 但是,如果你真的想保留当前的结构,并用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM