我有以下结构:银行有姓名和办事处列表。 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();
非常感谢任何帮助。
答案 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
联合关联。此外,您应该调查在使用二级缓存时对二级缓存的影响,并将此集合缓存在那里。