Spring Data JPARepository:如何有条件地获取子实体 [英] Spring Data JPARepository: How to conditionally fetch children entites

查看:277
本文介绍了Spring Data JPARepository:如何有条件地获取子实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我可以在一个单独的查询中获取子实体,但为了这样做,我需要配置我的存储库或实体不检索任何孩子。不幸的是,我似乎无法找到如何做到这一点的任何策略。 FetchPolicy 会被忽略,并且 EntityGraph 只有在指定我想要检索的实体时才有用。



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



我希望能够这样做:

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

问题是spring-data急切地提取联系人。



Account Entity类看起来像这样:




$ b

  @Entity 
@Table(name =accounts)
public class Account
{
protected String accountId;
protected Collection<联系人>联系人;

@OneToMany
//@OneToMany(fetch=FetchType.LAZY) - >不起作用,Spring存储库忽略此
@JoinColumn(name =account_id,referencedColumnName =account_id)
public Collection< Contact> getContacts()
{
return contacts;
}

// getters& setters

}

AccountRepository类看起来像这样:



  public interface AccountRepository扩展了JpaRepository< Account,String> 
{
// @ EntityGraph ...< - has type = LOAD或FETCH,但都不能帮助我防止检索
帐户findOne(String id);
}


解决方案

如果没有调用getContacts()方法产生的结果,那么应该是正确的。



如果你喜欢更多的手动工作,并且真的想要控制这个(也许更多的上下文取决于在用例上)。我建议您从帐户实体中删除联系人,并将帐户映射到联系人中。

  @Entity 
@ Table(name =accounts)
public class Account
{
protected String accountId;
保护收藏<联系>联系人;

@Transient
public Collection<联系人> getContacts()
{
return contacts;
}

// getters& setters

}

然后在你的服务类中,你可以做类似:

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

希望这是您要找的。Btw,代码没有经过测试,所以您应该可能再次检查。


How can one configure their JPA Entities to not fetch related entities unless a certain execution parameter is provided.

According to Spring's documentation, 4.3.9. Configuring Fetch- and LoadGraphs, you need to use the @EntityGraph annotation to specify fetch policy for queries, however this doesn't let me decide at runtime whether I want to load those entities.

I'm okay with getting the child entities in a separate query, but in order to do that I would need to configure my repository or entities to not retrieve any children. Unfortunately, I cannot seem to find any strategies on how to do this. FetchPolicy is ignored, and EntityGraph is only helpful when specifying which entities I want to eagerly retrieve.

For example, assume Account is the parent and Contact is the child, and an Account can have many Contacts.

I want to be able to do this:

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

The problem is spring-data eagerly fetches the contacts anyways.

The Account Entity class looks like this:

@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

}

The AccountRepository class looks like this:

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

解决方案

The lazy fetch should be working properly if no methods of object resulted from the getContacts() is called.

If you prefer more manual work, and really want to have control over this (maybe more contexts depending on the use case). I would suggest you to remove contacts from the account entity, and maps the account in the contacts instead. One way to tell hibernate to ignore that field is to map it using the @Transient annotation.

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

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

    //getters & setters

}

Then in your service class, you could do something like:

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;
}

Hope this is what you are looking for. Btw, the code is untested, so you should probably check again.

这篇关于Spring Data JPARepository:如何有条件地获取子实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆