Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring get generic type class

I know this question has been asked often but I'm unable to find a solution. How can I get a generic type class name in a Spring injected repository?

Here it is my base repository

public interface UserRepository extends JpaRepository<User, Long>, IUserRepository<User>{
   User findByUsername(String username);
}

this is the interface

public interface IUserRepository<T> {
   public List<T> findAllValidEtSiteAndStructure();
}

and finally here it is the implementation

public class UserRepositoryImpl<T> implements IUserRepository<T> {

@PersistenceContext
private EntityManager em;

private Class< T > type;

@Override
public List<T> findAllValidEtSiteAndStructure() {
    final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication instanceof UserAuthentication) {
        final User currentUser = ((UserAuthentication) authentication).getDetails();
        return (List<T>) em.createQuery("FROM " + type.getName()+ " WHERE site=:site AND structure=:structure AND valid=:valid")
                .setParameter("site", currentUser.getInstallation().getSite())
                .setParameter("structure", currentUser.getInstallation().getStructure())
                .setParameter("valid", true)
                .getResultList();
    }
    return null;
}
}

how can I get type.name? Thanks in advance

like image 238
davidetrapani Avatar asked May 12 '15 22:05

davidetrapani


People also ask

How do you find the type of generic class?

If we want the actual type of a generic parameter, we should inject it to the class in another way (e.g. constructor parameter, abstract function that returns the actual type, etc...).

What is generic type class?

A generic type is a class or interface that is parameterized over types. We use angle brackets (<>) to specify the type parameter.

What is difference between class and generic class?

The generic class works with multiple data types. A normal class works with only one kind of data type.


2 Answers

Considering that you're using Spring Framework, use the code snippet bellow, I've tested and it worked just fine:

ResolvableType resolvableType = ResolvableType.forClass(UserRepository.class).as(JpaRepository.class);
System.out.println(resolvableType.getGeneric(0));//User
System.out.println(resolvableType.getGeneric(1));//Long
like image 184
s_bighead Avatar answered Oct 25 '22 09:10

s_bighead


Basically you can't get the generic type because of type erasure.

What I would do is add an abstract method to UserRepositoryImpl that returns the relevant type:

public abstract Class getType();

And then I would create specific instances for UserRepositoryImpl for which the type is already known at compile time. For example:

public class StudentRepository extends UserRepositoryImpl<Student> {
  public Class getType() {
    return Student.class;
  }
}
like image 23
Avi Avatar answered Oct 25 '22 10:10

Avi