相关疑难解决方法(0)

JPA eager fetch不加入

JPA的获取策略到底控制了什么?我无法发现渴望和懒惰之间的任何区别.在这两种情况下,JPA/Hibernate都不会自动加入多对一关系.

示例:Person有一个地址.地址可以属于很多人.JPA带注释的实体类看起来像:

@Entity
public class Person {
    @Id
    public Integer id;

    public String name;

    @ManyToOne(fetch=FetchType.LAZY or EAGER)
    public Address address;
}

@Entity
public class Address {
    @Id
    public Integer id;

    public String name;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用JPA查询:

select p from Person p where ...
Run Code Online (Sandbox Code Playgroud)

JPA/Hibernate生成一个SQL查询以从Person表中进行选择,然后为每个人选择一个不同的地址查询:

select ... from Person where ...
select ... from Address where id=1
select ... from Address where id=2
select ... from Address where id=3
Run Code Online (Sandbox Code Playgroud)

这对于大型结果集非常糟糕.如果有1000个人,则会生成1001个查询(1个来自Person,1000个来自地址).我知道这是因为我正在查看MySQL的查询日志.我的理解是,将地址的提取类型设置为eager会导致JPA/Hibernate自动使用连接进行查询.但是,无论获取类型如何,它仍会为关系生成不同的查询.

只有当我明确告诉它加入时它才真正加入:

select p, a from Person p left join p.address …
Run Code Online (Sandbox Code Playgroud)

java hibernate jpa join

106
推荐指数
6
解决办法
12万
查看次数

使用JPA Criteria API,您是否可以执行只获得一次连接的获取连接?

使用JPA 2.0.似乎默认情况下(没有显式提取),@OneToOne(fetch = FetchType.EAGER)在1 + N个查询中提取字段,其中N是包含定义与不同相关实体的关系的实体的结果数.使用Criteria API,我可能会尝试避免如下:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
Join<MyEntity, RelatedEntity> join = root.join("relatedEntity");
root.fetch("relatedEntity");
query.select(root).where(builder.equals(join.get("id"), 3));
Run Code Online (Sandbox Code Playgroud)

理想情况下,上述内容应与以下内容相同:

SELECT m FROM MyEntity m JOIN FETCH myEntity.relatedEntity r WHERE r.id = 3
Run Code Online (Sandbox Code Playgroud)

但是,条件查询导致根表不必要地连接到相关实体表两次; 一次用于获取,一次用于where谓词.生成的SQL看起来像这样:

SELECT myentity.id, myentity.attribute, relatedentity2.id, relatedentity2.attribute 
FROM my_entity myentity 
INNER JOIN related_entity relatedentity1 ON myentity.related_id = relatedentity1.id 
INNER JOIN related_entity relatedentity2 ON myentity.related_id = relatedentity2.id 
WHERE relatedentity1.id = 3
Run Code Online (Sandbox Code Playgroud)

唉,如果我只进行获取,那么我没有在where子句中使用的表达式.

我错过了什么,或者这是Criteria API的限制?如果是后者,这是否在JPA 2.1中得到纠正,还是有任何特定于供应商的增强功能?

否则,最好放弃编译时类型检查(我意识到我的示例不使用元模型)并使用动态JPQL TypedQueries.

java jpa jpql criteria-api

24
推荐指数
2
解决办法
5万
查看次数

Hibernate 为 @ManyToOne JPA 注释属性创建 N+1 个查询

我有这些课程:

@Entity
public class Invoice implements Serializable {
    @Id
    @Basic(optional = false)
    private Integer number;

    private BigDecimal value;

    //Getters and setters
}

@Entity
public class InvoiceItem implements Serializable {
    @EmbeddedId
    protected InvoiceItemPK invoiceItemPk;

    @ManyToOne
    @JoinColumn(name = "invoice_number", insertable = false, updatable = false)
    private Invoice invoice;

    //Getters and setters
}
Run Code Online (Sandbox Code Playgroud)

当我运行此查询时:

session.createQuery("select i from InvoiceItem i").list();
Run Code Online (Sandbox Code Playgroud)

它执行一个查询以从 InvoiceItem 中选择记录,如果我有 10000 个发票项目,它会生成 10000 个附加查询以从每个 InvoiceItem 中选择发票。

我认为如果可以在单个 sql 中获取所有记录会好得多。实际上,我觉得奇怪为什么它不是默认行为。

那么,我该怎么做呢?

java hibernate jpa many-to-one select-n-plus-1

7
推荐指数
2
解决办法
5381
查看次数

标签 统计

java ×3

jpa ×3

hibernate ×2

criteria-api ×1

join ×1

jpql ×1

many-to-one ×1

select-n-plus-1 ×1