7

I have a Spring application. After login, I am invoking getUserByEmail() method.

I only need user and role data. Based on role I am going to display different views, Each view has different data and requiring different child entity of User.

Seems like I have to call getUserByEmail() with different child entity.

This is my partial code involving Entities:

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. Is it possible to have two graph of User objects with same query name? Because I need different data for different views.

  2. Also, when switching to a new view (new call in spring controller), transaction from previous view will be closed already and I have to make new call to have different data with user. I don't understand how fetch lazy is helpful if you are not in same transaction service method, unless I am not missing something.

For example if I need order data in "orderWiew.html" lazy load of order is not going to help I have to make another full call to same user data and additional Order data

JavaHopper
  • 5,567
  • 1
  • 19
  • 27
smile
  • 498
  • 7
  • 18
  • Possible duplicate of [Spring Data JPA And NamedEntityGraphs](http://stackoverflow.com/questions/31943989/spring-data-jpa-and-namedentitygraphs) – Réda Housni Alaoui Feb 09 '17 at 09:39

1 Answers1

7

Just a sugestion about using multiple entity graphs: where I work we used the fact Spring Data can use multiple prefixes for query methods. We set a convention that methods with different prefixes have different entity graphs. So, for example, findUserByEmail(String) could use a more lazy graph than readUserByEmail(String).

Unfortunately I don't think Spring Data supports passing the entity graph to use in a dynamic way. You could implement it and have it added to your repository, though. To do that you should:

Create an interface that declares the new method (but does not extend JpaRepository or other repository interfaces)

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

Make your repository interface extend that interface.

public interface UserRepository extends JPaRepository<User,Long>, UserCustomOperations{
    // Not much to do here anymore
}

Create a class that implements your custom behaviour in the same package, with a suffix of Impl (by default).

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
    }
}
Suneet Khurana
  • 431
  • 5
  • 10
Apokralipsa
  • 2,674
  • 17
  • 28
  • Thanks @Apokralipsa, I think your solution is very valid, and will provide option to give any name to the query. Only thing that I was trying to prevent to inject EntityManager into my implementation. But seems like this is the only option. – smile Jul 06 '15 at 23:39
  • I wonder, anytime calling different query for same object(User in this case), will User object be loaded freshly from DB with its children or User will be loaded from cache but unloaded child will be loaded from DB? – smile Jul 07 '15 at 00:04
  • If you don't want to inject the entity manager then consider creating a JPQL named query with a FETCH JOIN (http://docs.oracle.com/cd/E15523_01/apirefs.1111/e13946/ejb3_langref.html#ejb3_langref_fetch_joins). You can then annotate the method in your repository with @Query and have it execute that JPQL. – Apokralipsa Jul 07 '15 at 10:19