Question

JPA and Hibernate have some methods with some genericized return types that I don't understand, e.g.,

public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass)

in AbstractEntityManagerImpl. I would have expected a return type of TypedQuery<T>. What does the <T> that precedes the TypedQuery<T> indicate?

This isn't a purely theoretical question on my part. I have some code that is giving me compilation errors.

    TypedQuery<LogEntity> query =
            entityManager.createNamedQuery(
                    "LogEntity.findByContentionText",
                    LogEntity.class);

The error reads:

method createNamedQuery in interface javax.persistence.EntityManager cannot be applied to given types;
  required: java.lang.String
  found: java.lang.String,java.lang.Class<mypackage.LogEntity>
  reason: actual and formal argument lists differ in length

This is somewhat misleading, because EntityManager.createNamedQuery is overloaded with:

public Query createNamedQuery(String name);

and

public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass);

The error refers to the first definition, whereas I am trying to match the second definition. What am I doing wrong?

Was it helpful?

Solution

The parameter type of a generic class/method must be declared at some point. For a generic class, you declare it in the class definition:

class X<T> {}

On the other hand, for a generic method within a class that is not generic, you have to declare it in the method declaration itself:

class NotGeneric{
  public <T> X<T> genericMethod(String s, Class<T> cls){}
}

Finally, your error is probably due to a different issue, e.g., you might have jar files for javax.persistence 1.x or both 1.x and 2.0 at the same time in your classpath. The overloaded method was added in 2.0.

OTHER TIPS

The return type is TypedQuery<T>. The <T> before the return type means that the method is a generic method, having a single generic type called T.

It thus means that the caller of the method decides the type of the returned TypedQuery, by passing a Class instance. If you pass Foo.class as argument, the method will return a TypedQuery<Foo>.

Other generic methods don't take a generic type as argument, and the caller can decide which type to use by using, for example

Collections.<Foo>emptyList();

Your code doesn't compile because you have an old version of JPA in your classpath, where the method createNamedQuery(String, Class) doesn't exist (see http://docs.oracle.com/javaee/5/api/javax/persistence/EntityManager.html for the documentation of this old version).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top