解决JPA懒加载典型的N+1问题-注解@NamedEntityGraph

本文介绍了在Java应用中遇到的JPA懒加载引发的N+1问题,特别是在处理树形结构的实体时。通过详细步骤展示了如何不改变懒加载策略,也不使用原生SQL,而是利用@NamedEntityGraph注解进行联表查询,有效解决了这个问题。在示例中,作者给出了Area实体的自关联设计以及相应的DAO操作,并通过测试验证了解决方案的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为在设计一个树形结构的实体中用到了多对一,一对多的映射关系,在加载其关联对象的时候,为了性能考虑,很自然的想到了懒加载。

也由此遇到了N+1的典型问题 : 通常1的这方,通过1条SQL查找得到1个对象,而JPA基于Hibernate,fetch策略默认为select(并非联表查询),由于关联的存在 ,又需要将这个对象关联的集合取出,集合数量是N,则要发出N条SQL,于是本来的1条联表查询SQL可解决的问题变成了N+1条SQL

我采取的解决方法是 : 不修改懒加载策略,JPA也不写native SQL,通过联表查询进行解决。

如果对该例子比较感兴趣或者觉得言语表达比较啰嗦,可查看完整的demo地址 : https://github.com/EalenXie/springboot-jpa-N-plus-One

场景如下 : 

  我设计了一个典型的二叉树结构实体叫做Area,代表的含义是区域 (省、市、区)。省是树的一级根节点,市是省的子节点,区是市的子节点。如 : 广东省,广州市,天河区

  1 . Area实体设计采用自关联,关联的子集fetch策略为懒加载。

package name.ealen.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.util.List;

/**
 * Created by EalenXie on 2018/10/16 16:49.
 * 典型的 多层级 区域关系
 */

@Entity
@Table(name = "jpa_area")
public class Area {


    /**
     * Id 使用UUID生成策略
     */
    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
    private String id;

    /**
     * 区域名
     */
    private String name;

    /**
     * 一个区域信息下面很多子区域(多级) 比如 : 广东省  (子)区域 : 广州市  (孙)子区域 : 天河区
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id")
    @JsonIgnore
    private Area parent;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    private List<Area> children;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值