Search code examples
javajpaentitygraph

JPA EntityGraph based on meta model containing MappedSuperclass not possible?


I'm trying to use the type safe method EntityGraph.addAttributeNodes(Attribute<T, ?> ... attribute) for constructing my entity graph. I have a type hierarchy with a @MappedSuperclass that basically looks like this:

@MappedSuperclass
public abstract class BaseEntity
{
    @Id
    private int dbid;
}

@Entity
public class Entity extends BaseEntity
{
    private String someAttribute;
}

EclipseLink creates this meta model:

@Generated(value="EclipseLink-2.5.2.v20140319-rNA", date="2015-08-07T10:46:31")
@StaticMetamodel(BaseEntity.class)
public abstract class BaseEntity_ { 
    public static volatile SingularAttribute<BaseEntity, Integer> dbid;
}

@Generated(value="EclipseLink-2.5.2.v20140319-rNA", date="2015-08-07T10:46:31")
@StaticMetamodel(Entity.class)
public class Entity_ extends BaseEntity_ {
    public static volatile SingularAttribute<Entity, String> someAttribute;
}

The problem is that I cannot refer to the dbid attribute with the entity graph API:

EntityGraph<Entity> graph = em.createEntityGraph( Entity.class );
graph.addAttributeNodes( Entity_.dbid ); // does not compile: "The method addAttributeNodes(String...) in the type EntityGraph<Entity> is not applicable for the arguments (SingularAttribute<BaseEntity,Integer>)"

For this to work, wouldn't the method signature need to look like this: EntityGraph.addAttributeNodes(Attribute<? super T, ?> ... attribute)? Is this a shortcoming of the specification or am I overlooking something?

It seems to me that this is a problem related to the one described here. As the author of that question points out, the Criteria API get method for singular attributes does indeed use ? super X to define the type parameter.

But even when I add the someAttribute node, there's still this somewhat ugly warning, which I presume can only be suppressed at best:

graph.addAttributeNodes( Entity_.someAttribute ); // generates warning: "Type safety: A generic array of Attribute<Entity,?> is created for a varargs parameter"

Solution

  • I'd agree.

    Clearly if you changed your code to

    EntityGraph<BaseEntity> graph = em.createEntityGraph(BaseEntity.class);
    graph.addAttributeNodes(BaseEntity_.dbid );
    

    then it would compile. The problem does indeed seem to be in the spec/API where it has EntityGraph's generic type being applied to the addAttributeNodes argument (hence not allowing superclass fields). Yes, it does say that "T" is the type of the root entity, but that can't mean that they expect people to always use the MappedSuperclass?

    I'd also confirm that by using "? super T" for the Attribute generic type fixes it (taking a javax.persistence jar source and modifying/rerunning).

    I raised it as an issue on JPA, not that I'd recommend holding breath for an update