使用Spring的JPA EntityGraph实现不同视图。

7
我有一个Spring应用程序。登录后,我调用getUserByEmail()方法。
我只需要用户和角色数据。根据角色,我将显示不同的视图,每个视图具有不同的数据并需要User的不同子实体。
看起来我必须使用不同的子实体调用getUserByEmail()。
这是涉及实体的部分代码:
EntityGraph(value = "withAddresses", type = EntityGraphType.FETCH)
public class User{
  public firstName;
  public lastName;

  @OneToMany(fetch = FetchType.LAZY)
  public List<Address> addresses

  @OneToMany(fetch = FetchType.LAZY)
  public List<Order> orders;             
 }

 public userRepository extend jPaRepository(User.class,Long){
  @EntityGraph(name="withAdresses")
  getUserByEmail(String email)

  /* if possible */
  @EntityGraph(name="withOrder")
  getUserByEmail(String email)
 }
  1. 有没有可能使用相同的查询名称来拥有两个用户对象的图表? 因为我需要不同的数据来展示不同的视图。
  2. 此外,当切换到新视图(在Spring控制器中进行新调用)时,之前视图的事务已经关闭了,我必须进行新的调用才能获得与用户不同的数据。除非我遗漏了什么,否则我不明白如果您不在同一个事务服务方法中,如何使用fetch lazy会有所帮助。

例如,如果我需要在“orderWiew.html”中获取订单数据,则延迟加载订单将无法帮助我,我必须对相同的用户数据和其他订单数据进行另一个完整的调用。


可能是Spring Data JPA和NamedEntityGraphs的重复问题。 - Réda Housni Alaoui
1个回答

7

关于使用多个实体关系图的建议:我们工作的地方,利用Spring Data可以使用多个前缀查询方法的事实。我们制定了一个规范,具有不同前缀的方法具有不同的实体关系图。例如,findUserByEmail(String)可以使用比readUserByEmail(String)更慢的图。

不幸的是,我认为Spring Data不支持以动态方式传递要使用的实体关系图。但是,您可以实现它并将其添加到存储库中。要做到这一点,您应该:

创建一个声明新方法的接口(但不扩展JpaRepository或其他存储库接口)

public interface UserCustomOperations{
    User findUserByEmail(String email, String entityGraph);
}

让你的仓库接口扩展该接口。
public interface UserRepository extends JPaRepository<User,Long>, UserCustomOperations{
    // Not much to do here anymore
}

创建一个类,实现自定义行为,放在同一个包中,并使用Impl作为后缀(默认情况下)。
public class  UserRepositoryImpl implements UserCustomOperations{
    public User findUserByEmail(String email, String entityGraph){
        // Inject the EntityManager and execute standard Jpa query with the entity graph set
    }
}

谢谢@Apokralipsa,我认为你的解决方案非常有效,并且将提供选项来为查询命名。唯一的问题是我试图防止将EntityManager注入到我的实现中。但似乎这是唯一的选择。 - smile
我想知道,每次调用相同对象(在这种情况下为用户)的不同查询时,用户对象是否会从数据库中重新加载其子项,还是用户将从缓存中加载,但未加载的子项将从数据库中加载? - smile
如果您不想注入实体管理器,请考虑使用FETCH JOIN创建JPQL命名查询 (http://docs.oracle.com/cd/E15523_01/apirefs.1111/e13946/ejb3_langref.html#ejb3_langref_fetch_joins)。然后,您可以在仓库中的方法上使用@Query进行注释,并让其执行该JPQL语句。 - Apokralipsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接