Hibernate ManyToMany - 仅返回唯一元素

时间:2012-07-16 13:09:02

标签: java hibernate

我有三张桌子:

Company
id  name
1   Fred Co.

Person
id   name
1    Fred

Employee
id company_id person_id rank
1  1          1         1
2  1          1         2

现在排名由不同的应用程序使用,但是对于我正在使用的内容我并不关心它。我想要做的是创建一个hibernate映射(通过域模型),它只返回唯一的员工。

我目前有

class Person {
    @Column(name = "id")
    Long id;

    @Column(name = "name")
    String id;
}

class Company {
    @Column(name = "id")
    Long id;

    @Column(name = "name")
    String id;

    @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "EMPLOYEE", 
                joinColumns = { @JoinColumn(name = "COMPANY_ID") },
                inverseJoinColumns = { @JoinColumn(name = "PERSON_ID") })
    @LazyCollection(LazyCollectionOption.EXTRA)
    List<Person> employees = new ArrayList<Person>();
}

但这意味着fredCo.employees.size() == 2。如何过滤以便只返回唯一的人?

我想通过域名模式这样做。

编辑:虽然上面的例子很小,但在现实生活中,Person对象非常庞大,每个公司有1000名员工(因此更加懒惰)。

现在我可以(并且有)获得

companyDao.getEmployeesFor(Company...)
companyDao.getEmployeeCountFor(Company...)

但感觉有点icky我想在没有Dao的情况下做到这一点。

1 个答案:

答案 0 :(得分:2)

如果总是设置排名并且第一个记录的排名始终为“1”,那么您可以将一个简单的@ Where / @ WhereJoinTable子句添加到将集合限制为排名为1的记录的映射中。

https://access.redhat.com/knowledge/docs/en-US/JBoss_Enterprise_Application_Platform/5/html/Hibernate_Annotations_Reference_Guide/entity-hibspec-collection.html

另一种方法是将集合更改为Set,并在Person上实现不涉及'rank'字段的equals()方法。

更新

好的,正如您之前所说,这不起作用。我已经做了一些测试,似乎当在一个关联上定义@LazyCollection时,无论如何都会忽略@Where对此关联的限制。在extra-lazy集合上调用size()实际上会导致Hibernate对数据库发出count()查询。附加条款未附加。

为什么@Where应该被忽略我不知道但是在其他地方已经查询过,这似乎是一个悬而未决的问题:

https://forum.hibernate.org/viewtopic.php?f=9&t=988631&view=previous

https://hibernate.onjira.com/browse/HHH-3319

我认为您仍然可以通过创建一个额外的Employee实体来执行您想要的操作,该实体映射到使用以前的SQL内部查询定义的VIEW - 然后在db级别完成过滤。将实体映射到视图与表相同。

然后用公司和Person to Employee中的两个一对多关联替换你的多对多。