Hibernate选择父项列表,子项匹配子参数

时间:2016-03-19 15:16:16

标签: java hibernate

我有以下结构:银行有姓名和办事处列表 Office 具有城市属性。

如何使用hql选择银行及其自己的办事处列表?>

代码:
银行

@Entity
@Table(name = "BANKS")
public class Bank {
    public Bank() {
    }

    public Bank(String name) {
        this.name = name;
    }

    @Id
    @Column(name = "ID")
    @GeneratedValue
    private int id;

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

    /*@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)*/
    @OneToMany(mappedBy = "bank", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    /*@JoinColumn(name = "BANK_ID")*/
    private List<Office> officeList;

办公室

@Entity
@Table(name = "OFFICES")
public class Office {
    public Office() {
    }

    public Office(String city, String address, String workingHours, Bank bank) {
        this.city = city;
        this.address = address;
        this.workingHours = workingHours;
        this.bank = bank;
    }

    @Id
    @Column(name = "ID")
    @GeneratedValue
    private int id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "BANK_ID")
    @JsonBackReference
    private Bank bank;

    public void setBank(Bank bank) {
        this.bank = bank;
    }

    public Bank getBank() {
        return bank;
    }

    @Column(name = "CITY")
    private String city;

    @Column(name = "ADDRESS")
    private String address;

    @Column(name = "WORKING_HOURS")
    private String workingHours;

我写过请求但是错误:

sessionFactory.getCurrentSession().createQuery("select b from Bank b join b.officeList o" +
                "    where o.city = ?").setString(0, city).list();

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

关于第一点,由于您加入了一个集合,因此可以使用重复项,您可以使用distinct轻松删除它们:

select distinct b from Bank b join b.officeList o where o.city = :city

第二点(officeList仅包含匹配属性)在概念上要复杂得多。

关键是在初始化officeList实例的Bank集合期间,Hibernate会加载与相应银行关联的所有办公室。这就是Hibernate应该做的事情:反映对象图中的数据库状态。这与您加入的实体/表以及您在用于检索银行的原始查询中指定的where条件无关。

但是,可以在使用[left] join fetch构造加载父项的同一查询中初始化子关联。例如,要将所有银行与所有办事处一起加载到一个查询中,您可以执行以下操作:

select distinct b from Bank b left join fetch b.officeList

Hibernate支持别名并在fetch条件下进一步使用where个连接的实体。这样,您基本上只使用数据库中元素的子集初始化集合。因此,要实现您的需求,您可以将查询更改为:

select distinct b from Bank b join fetch b.officeList o where o.city = :city

但是,请记住,JPA规范不支持在查询中过滤条件中使用fetch联合关联。此外,您应该调查在使用二级缓存时对二级缓存的影响,并将此集合缓存在那里。