【问题标题】:JPA uses subquery instead of joinJPA 使用子查询而不是联接
【发布时间】: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


    【解决方案1】:

    您似乎正在使用“member of”谓词来呈现此 SQL。您“想要”的 SQL 不包括 customer_id 的过滤器,但看起来您实际上想要这个过滤器,因为您编写了某种代码来应用谓词的成员。

    【讨论】:

      猜你喜欢
      • 2011-11-15
      • 2023-03-11
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 2019-05-27
      相关资源
      最近更新 更多