当前位置: 首页 > 知识库问答 >
问题:

Spring数据JPARepository:如何有条件地获取子实体

梅跃
2023-03-14

如何将其JPA实体配置为不获取相关实体,除非提供了特定的执行参数。

根据Spring的文件4.3.9。配置Fetch和LoadGraphs时,需要使用EntityGraph注释来指定查询的Fetch策略,但这并不能让我在运行时决定是否要加载这些实体。

我可以在单独的查询中获取子实体,但为了做到这一点,我需要将我的存储库或实体配置为不检索任何子实体。不幸的是,我似乎找不到任何关于如何执行此操作的策略。FetchPolicy被忽略,并且EntityGraph仅在指定我想要急切检索哪些实体时有用。

例如,假设帐户是父帐户,联系人是子帐户,并且一个帐户可以有许多联系人。

我希望能够做到这一点:

if(fetchPolicy.contains("contacts")){
  account.setContacts(contactRepository.findByAccountId(account.getAccountId());
}

问题是Spring data急切地获取联系人。

帐户实体类如下所示:

@Entity
@Table(name = "accounts")
public class Account
{
    protected String accountId;
    protected Collection<Contact> contacts;

    @OneToMany
    //@OneToMany(fetch=FetchType.LAZY) --> doesn't work, Spring Repositories ignore this
    @JoinColumn(name="account_id", referencedColumnName="account_id")
    public Collection<Contact> getContacts()
    {
        return contacts;
    }

    //getters & setters

}

AccountRepository类如下所示:

public interface AccountRepository extends JpaRepository<Account, String>
{
    //@EntityGraph ... <-- has type= LOAD or FETCH, but neither can help me prevent retrieval
    Account findOne(String id);
}

共有3个答案

叶卓君
2023-03-14

请查找一个运行JPA 2.1的示例。

设置您只想加载的属性(带有属性节点列表):

具有实体图注释的实体:

@Entity
@NamedEntityGraph(name = "accountGraph", attributeNodes = { 
  @NamedAttributeNode("accountId")})
@Table(name = "accounts")
public class Account {

    protected String accountId;
    protected Collection<Contact> contacts;

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(name="account_id", referencedColumnName="account_id")
    public Collection<Contact> getContacts()
    {
        return contacts;
    }
}

您的自定义界面:

public interface AccountRepository extends JpaRepository<Account, String> {

    @EntityGraph("accountGraph")
    Account findOne(String id);
}

只有“帐户ID”属性将被急切加载。所有其他属性将在访问时延迟加载。

何松
2023-03-14

您可以为此使用@Transactional

为此,您需要缓慢地获取您的帐户实体。

事务性注释应放置在所有不可分割的操作周围。

在您的服务层中写入方法,该方法接受一个标志以急切地获取联系人。

@Transactional
public Account getAccount(String id, boolean fetchEagerly){
    Account account = accountRepository.findOne(id);

    //If you want to fetch contact then send fetchEagerly as true
    if(fetchEagerly){
        //Here fetching contacts eagerly
        Object object = account.getContacts().size();   
    }
}

@Transactional是一种服务,它可以在单个事务中进行多个调用,而无需关闭与endpoint的连接。

希望您觉得这很有用。:)

有关更多详细信息,请参阅此链接

毕泽宇
2023-03-14

如果没有调用由getContacts()生成的object方法,则延迟提取应该可以正常工作。

如果您喜欢更多的手工工作,并且真的想控制这一点(可能需要更多的上下文,具体取决于用例)。我建议您从帐户实体中删除联系人,并将该帐户映射到联系人中。告诉hibernate忽略该字段的一种方法是使用@Transient注释对其进行映射。

@Entity
@Table(name = "accounts")
public class Account
{
    protected String accountId;
    protected Collection<Contact> contacts;

    @Transient
    public Collection<Contact> getContacts()
    {
        return contacts;
    }

    //getters & setters

}

然后在您的服务类中,您可以执行以下操作:

public Account getAccountById(int accountId, Set<String> fetchPolicy) {
    Account account = accountRepository.findOne(accountId);
    if(fetchPolicy.contains("contacts")){
        account.setContacts(contactRepository.findByAccountId(account.getAccountId());
    }
    return account;
}

希望这就是您正在寻找的。顺便说一句,代码未经测试,因此您可能应该再次检查。

 类似资料:
  • 我读过Spring数据JPARepository:如何有条件地获取子实体。但我想使用方便的JPA注释,而不是手动连接所有子级。 假设我有以下型号: 获取凭据列表(credentialList)和操作列表(actionList)可能是一项耗时的操作(连接获取等)。我不想自动获取凭据列表,也不想自动获取操作列表。但当我访问它们时,我希望它们是一个空列表,而不是懒散的初始化异常。 即使我没有在查询中专门

  • 我试图为父对象创建一个NamedQuery,它从数据库中检索所有可用的父对象,并有条件地在同一个查询中获取一些子对象。例如,查询应该检索所有父对象,并获取每个父对象的年=2012的子对象。不应该获取其余的子对象。我试图用左连接FETCH来玩,但结果是一些父对象也被排除在外。但话说回来,我是FETCH语句的新手。 有没有办法完成上述任务?非常感谢您的帮助。我的父对象的相关代码如下所示:

  • 我有这个实体(为简洁起见省略注释): 我必须得到一个不同的值的列表为一个特定的 在我的JpaRepository中我有以下内容: 如果没有注释,则返回ID,而不是值。生成的SQL如下所示: 但我需要的是不同的类别,而不是产品实体。除此之外,我在上面添加了注释。但现在我得到了这个错误: 但是我不能将添加到结果列表中,因为这会使无效,因为是主键。 所以我要么需要一个合适的方法名来自动生成查询,要么需要

  • 问题内容: 我想获取基于条件选择的数据帧行数。我尝试了以下代码。 输出: 输出显示数据帧中每一列的计数。相反,我需要获得满足以上所有条件的单一计数?这该怎么做?如果您需要有关我的数据框的更多说明,请告诉我。 问题答案: 您要的是所有条件都为真的条件,所以答案是len,除非我误解了您的要求

  • 我有一个带有此模式的数据库: 我测试了这段代码,但我无法从数据库中获得任何消息。我会感谢你的帮助。

  • 问题内容: 我想在浏览器遵循ui-router动态创建的链接之前验证某些条件。 我正在调查,但无法从那里访问。我还需要在应用程序中的多个地方使用它,这会很麻烦。 请记住,它链接到(一起工作),因此我无法删除,也不能在称为with的函数内使用。 应该在a 和on 内评估条件(在转换之前,可以取消条件) 我需要这样的东西: 我试过了: 和 甚至 但是不起作用。 沙盒 问题答案: 这个答案激发了我创建一