【发布时间】:2021-10-23 19:39:39
【问题描述】:
我有一个看起来像这样的实体:
@Entity(name = "File")
@Table(name = "files", schema = "myschema")
public class FileEntity implements Serializable {
@Id
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "owner_id", insertable = false, updatable = false)
private CustomerEntity owner;
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name = "file_customers", //joining table containing customer_id and file_id
joinColumns = @JoinColumn(name = "file_id")
)
@Column(name = "customer_id")
private Set<Long> visibleTo;
}
我将它与 CriteriaBuilder 结合使用,如下所示:
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<FileEntity> cr = criteriaBuilder.createQuery(FileEntity.class);
final Root<FileEntity> root = cr.from(FileEntity.class);
root.join("owner", JoinType.LEFT).alias("owner");
//add conditions, sort orders, etc...
final TypedQuery<FileEntity> query = entityManager.createQuery(cr);
query.getResultList();
现在当我通过所有者字段查询时,我得到了这个 sql:
select * from myschema.files as files
left outer join myschema.customer as customer on files.owner_id=customer.id
where customer.name=?
但是当我查询 visibleTo 字段时,我得到一个子查询:
select * from myschema.files as files
left outer join myschema.customer as customer on files.owner_id=customer.id
where ? in (select visibleTo.customer_id from myschema.file_customers as visibleTo where files.id=visibleTo.file_id)
虽然我喜欢得到的查询是这样的:
select * from myschema.files as files
left outer join myschema.customer as customer on files.owner_id=customer.id
left outer join myschema.file_customers as visibleTo on files.id=visibleTo.file_id
where visibleTo.id = ?
子查询版本比我的 postgres(10.14) 数据库中的联接版本慢 2 个数量级以上。
添加root.join("visibleTo", JoinType.LEFT).alias("visibleTo"); 创建我想要的连接,但仍然在 where 子句中使用子查询。
我还考虑过使用@ManyToMany 而不是@ElementCollection,但这意味着我将不得不不必要地加载完整的对象而不仅仅是id。
【问题讨论】:
标签: java postgresql hibernate jpa criteria