Spring Data JPARepository:如何有条件地获取子条目

2022-09-01 08:58:18

如何配置其JPA实体,除非提供某个执行参数,否则不获取相关实体。

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

我可以将子实体放在单独的查询中,但为了做到这一点,我需要将我的存储库或实体配置为不检索任何子实体。不幸的是,我似乎找不到任何关于如何做到这一点的策略。 将被忽略,并且仅在指定要热切检索的实体时才有用。FetchPolicyEntityGraph

例如,假定是父级和子级,并且一个帐户可以有多个联系人。AccountContact

我希望能够做到这一点:

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

问题是,无论如何,spring数据都急切地获取联系人。

帐户实体类如下所示:

@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

}

帐户存储库类如下所示:

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

答案 1

如果调用 getContacts() 生成的对象方法,则惰性 fetch 应该正常工作。

如果您更喜欢更多的手动工作,并且真的想要控制这一点(可能会有更多的上下文,具体取决于用例)。我建议您从客户实体中删除联系人,并在联系人中映射客户。告诉休眠忽略该字段的一种方法是使用@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;
}

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


答案 2

您可以使用它。@Transactional

为此,您需要懒惰地获取您的帐户实体。

@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是一种服务,可以在单个事务中进行多次调用,而无需关闭与端点的连接。

希望你觉得这有用。:)

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


推荐