【问题标题】:How to achive lazy loading using spring data jpa?如何使用spring data jpa实现延迟加载?
【发布时间】:2019-04-29 23:56:42
【问题描述】:

在我的项目中,我使用 Spring Data JPA 并为我的数据获取类扩展了 JpaRepository 接口。

OrganizationMaster 类:

  @Entity
  @Table(name="organization_master")
  public class OrganizationMaster  {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="organization_id")
    private int organizationId;

    @OneToMany(mappedBy="organizationMaster")
        private List<CompanyMaster> companyMasters;
    }

公司大师班:

Entity
@Table(name="company_master")
public class CompanyMaster {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="company_id")
    private int companyId;


    @ManyToOne
    @JoinColumn(name="organization_id")
    private OrganizationMaster organizationMaster;
}

我的控制器

@RequestMapping(value = "/GetOrganization", method = RequestMethod.GET)
    public
    @ResponseBody
    List<OrganizationMaster> getOrganization(){
       return organizationService.getOrganization();
    }

组织服务:

public interface OrganizationService {
   List<OrganizationMaster> getOrganization();
}

OrganizationServiceImpl:

@Service
public class OrganizationServiceImpl implements OrganizationService{
    @Autowired
    private OrganizationDao organizationDao;
    @Override
    public List<OrganizationMaster> getOrganization() {
        return organizationDao.findAll();
    }
}

OrganizationDao 接口:

public interface OrganizationDao extends JpaRepository<OrganizationMaster,Long> {
}

我的输出响应是: [{"organizationId":5,"companyMasters":[{"companyId":29},{"companyId":30}]}]

但我的需要是 [{"organizationId":5}]

当我尝试使用 findall() 方法从组织主机获取数据时,它还会根据关系从公司主机获取数据。如何使用 Spring Data JpaRepository 实现延迟获取(仅从组织主服务器获取数据

【问题讨论】:

  • 不,它没有。获取 CompanyMaster 实体的不是 findAll()。这是您在加载后对已加载的 OrganizationMaster 实体执行的操作。延迟加载并不意味着 JPA 永远不会加载它们。这意味着它只会在代码实际需要使用它们时才加载它们。因此,例如,如果您有System.out.println(organization.getCompanyMasters()),它将在那时加载它们,因为打印列表意味着打印列表中的每个元素,并且要打印一个元素,您需要拥有该元素,并且拥有该元素,你需要加载它。
  • 当我使用 System.out.println(organization) 时,它还会打印 companyMaster 值。
  • OrganizationMaster的toString()方法是什么?
  • 我只使用 getter 和 setter,没有 toString() 方法用于 OrganizationMaster
  • 如果您希望我们解释它的作用以及为什么它延迟加载 companyMasters,请发布代码。但无论如何,您要求 Spring 将 OarganizationMaster 序列化为 JSON 的简单事实将强制延迟加载,因为您没有将 Jackson 配置为忽略 companyMasters。

标签: java spring-boot spring-data-jpa


【解决方案1】:

所有 XToOne 关联都是默认的 EAGER。您具有双向关系,因此您应该在 @ManyToOne 端使用 FetchType.LAZY

@ManyToOne(fetch = FetchType.LAZY)

此外,如果您在序列化时使用任何序列化程序(如 json 序列化程序),它会调用 getter 方法,并且可能会导致不必要地加载惰性项。

另一个考虑因素是在使用 Lombok 时,@Data 注释会导致无需加载惰性项。所以在使用 Lombok 时要小心。

所以在你的情况下,因为你返回实体本身,而序列化它也序列化子实体,它会导致加载延迟子实体。

您需要返回一个仅代表您的父实体的 dto,以防止子实体的序列化。如果你用 getter 方法调用 child,它会从数据库中懒惰地加载子实体。

查看更多信息关联:

https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/

【讨论】:

  • @ManyToOne(fetch = FetchType.LAZY) 它也不起作用。在哪里使用@Data注解
  • 我明白了,就像我说的,你在你的控制器上返回实体,所以在序列化它时也序列化子关系。所以它在序列化时加载孩子懒惰。很明显,您可以在回复中看到子实体。
  • 您应该将您的实体转换为 dto 以防止子实体的序列化。
【解决方案2】:

我相信之前有人问过这个问题!你可以使用这个注释:

@OneToMany(fetch = FetchType.LAZY)

阅读这篇文章以获得更好的观点:

https://howtodoinjava.com/hibernate/lazy-loading-in-hibernate/

【讨论】:

    猜你喜欢
    • 2013-11-02
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多