【发布时间】:2018-05-15 21:06:40
【问题描述】:
我有一个实体,例如:
@Entity
class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, columnDefinition = "BIGINT")
private Long id;
@NotNull(message = NOT_NULL_CODE)
@Size(min = 5, max = 150, message = SIZE_CODE)
@Column(nullable = false, length = 150)
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organization_id", nullable = false)
@JsonBackReference("organization-brands")
private Organization organization;
// getters and setters
}
我的存储库定义了以下内容:
Page<Brand> findAllByOrganization(Organization organization, Pageable pageable);
这会产生以下查询:
select
brand0_.id as id1_1_,
brand0_.name as name2_1_,
brand0_.organization_id as organiza3_1_
from
brand brand0_
left outer join
organization organizati1_
on brand0_.organization_id=organizati1_.id
where
organizati1_.id=? limit ?
我想知道为什么会创建一个left outer join?我想可能是因为organization_id 是选择的一部分,所以我创建了一个仅包含name 和id 列的DTO 投影,但仍然包括left outer join。我找到了this bug report,但它的移动为零。
这与我有关的原因是因为left outer join 平均增加了 200 毫秒的查询时间。我还没有进行任何基准测试来确定这是否会随着更多数据行而呈指数增长。但是对于我当前的数据集,它是 200 毫秒。哎呀。
【问题讨论】:
-
可能是因为 Hibernate/JPA 需要引用来获取组织对象。因为你的 Brand 对象有一个 Organization 对象,不是很长的 fk
-
这也是我们的情况,我们使用 QueryDSL 库是为了更好地控制 jpa 查询,尤其是在运行返回 DTO 的小投影而不是完整实体的查询时。
-
可能与stackoverflow.com/a/17987718/1356423有关。试试
@ManyToOne(fetch = FetchType.LAZY, optional = false)。如果没有这个,我猜 Hibernate 必须检查表以查看是否设置代理或 null。 -
@MarcosVasconcelos 我很确定查询实体可能就是这种情况。但是使用 DTO 投影,我什至不要求组织。它不在选择中,它仍在添加该连接。
-
你查询方法返回
Page<Brand>。这个 DTO 在哪里?
标签: java hibernate spring-boot spring-data spring-data-jpa