Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA SubGraph to define fetchtype of an embedded property

I have an entity Ride which embeds an embeddable "entity" Route. Route has a List property towns with ManyToMany relation, so it has fetchtype LAZY (and I don't want to use EAGER). So I want to define an NamedEntityGraph for the entity Ride, to load load a Ride object with a Route with instantied List of towns. But when I deploy my war, I get this exception:

java.lang.IllegalArgumentException: Attribute [route] is not of managed type

Ride

@Entity
@NamedQueries({
@NamedQuery(name = "Ride.findAll", query = "SELECT m FROM Ride m")})
@NamedEntityGraphs({
@NamedEntityGraph(
        name = "rideWithInstanciatedRoute",
        attributeNodes = {
            @NamedAttributeNode(value = "route", subgraph = "routeWithTowns")
        },
        subgraphs = {
            @NamedSubgraph(
                    name = "routeWithTowns",
                    attributeNodes = {
                        @NamedAttributeNode("towns")
                    }
            )
        }
    )
})
public class Ride implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Embedded
    private Route route;

    // some getter and setter
}

Route

@Embeddable
public class Route implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManyToMany
    private List<Town> towns;

    // some getter and setter
}
like image 380
Helmosch Avatar asked Dec 18 '14 17:12

Helmosch


1 Answers

Looking at Hibernate's implementation of org.hibernate.jpa.graph.internal.AttributeNodeImpl lead us to the conclusion that @NamedAttributeNode cannot be:

  • simple types (Java primitives and their wrappers, strings, enums, temporals, ...)
  • embeddables (annotated with @Embedded)
  • element collections (annotated with @ElementCollection)
if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC || 
    attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED ) {
    throw new IllegalArgumentException(
        String.format("Attribute [%s] is not of managed type", getAttributeName())
    );
}

I didn't find similar restriction in JPA 2.1 spec, therefore it may be Hibernate's shortcoming.


In your particular case the problem is that @NamedEntityGraph refers to the Route class which is an embeddable, thus its usage in the entity graph seems to be forbidden by Hibernate (unfortunately).

In order to make it work you would need to change your entity model a little. A few examples that come into my mind:

  • define Route as entity

  • remove Route and move its towns field into Ride entity (simplifies the entity model)

  • move route field from Ride into Town entity, add map of routedTowns map to Ride entity:

     @Entity
     public class Ride implements Serializable {
         ...
         @ManyToMany(mappedBy = "rides")
         private Map<Route, Town> routedTowns;
         ...
     }
    
     @Entity
     public class Town implements Serializable {
         ...
         @ManyToMany
         private List<Ride> rides;
         @Embeddable
         private Route route;
         ...
     }
    

Of course the entity graph may require changes accordingly.

like image 188
wypieprz Avatar answered Oct 13 '22 21:10

wypieprz