访问外键列值而不获取关联记录

问题描述 投票:0回答:1

我正在从另一个开发堆栈切换到Java/Spring,我对Spring中的一些事情是如何完成的感到非常困惑。我很惊讶我找不到解决我的特定问题的方法。

考虑以下代码结构:

@Entity
class Parent {
}

@Entity
class Child {
    private String name;

    @ManyToOne
    private Parent parent;
}
  

在我的 API 控制器中,我想用

Child
列表进行响应。每个
Child
项目应包含一些
Child
字段(例如
name
)和
Parent
ID(并且没有其他
Parent
数据):

// JSON Response example
{
  "children": [
    {
      "name": "Child 1",
      "parent_id": 1
    },
    {
      "name": "Child 2",
      "parent_id": 2
    }
  ]
}

为了提供

parent_id
Spring+Hibernate+JPA 让我以这种方式访问
Parent
ID:

child.getParent().getId()

这不仅会导致不必要地从数据库中获取整个

Parent
记录及其所有字段,而且如果不使用任何 JOIN FETCH 或 EAGER LOAD 方法,在我的情况下还会导致 N + 1 问题。

但是

parent_id
是一个简单的
Child
的专栏。 即使未加载关联,它也应该免费提供!

有什么最佳方法可以实现我的目标吗?

java spring hibernate spring-data-jpa spring-data
1个回答
0
投票

这很有趣,但是当我使用

@EntityGraph
注解标记查询方法而不指定要获取哪些属性(关联)时,它不会执行额外的 SQL 查询来获取关联的
Parent
并且不会修改原始 SQL查询仅获取
Child
的数据。但同时,它能够计算
Parent
ID
值。

参见示例:

public interface ChildRepository extends JpaRepository<Child, Integer> {
    @Override
    @EntityGraph // Adding this annotation does the trick.
    List<Child> findAll();
}

现在当我以这种方式访问

Parent
ID时

List<Child> children = repository.findAll();
children.stream().map((child) -> child.getParent().getId());

它不会进行数据库查询来为每个

parent
获取
child
,并且不会急切加载(联接、获取)任何
parent
数据。同时它会工作并返回
parents
的 ID。

看起来使用

@EntityGraph
使得关联被急切加载(获取),因为
FETCH
是默认的
@EntityGraph
模式。但由于我没有指定要获取哪些关联,所以它没有获取任何内容。而且它没有延迟加载任何东西(没有进行额外的 SQL 查询),因为模式是
FETCH
。但是,它能够计算
child.getParent().getId()
,这是 目标 - 访问
parent
ID,而不获取
parent
记录

此外,正如预期的那样,使用此设置无法计算除

id
之外的任何其他字段值。例如,执行
child.getParent().getName()
失败并出现
LazyInitializationException
异常。


但是,我认为这不是正确的解决方案。看来应该有另一种简单而明确的方法来解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.