JPA SubGraph定义嵌入属性的fetchtype

时间:2014-12-18 17:34:42

标签: java jpa jpa-2.1 embeddable

我有一个实体 Ride ,它嵌入了一个可嵌入的“实体”路线 Route 有一个具有ManyToMany关系的List属性 towns ,所以它有fetchtype LAZY(我不想使用EAGER)。所以我想为实体 Ride 定义一个NamedEntityGraph,加载带有 Route Ride 对象,带有城镇的即时列表。 但是当我部署战争时,我得到了这个例外:

  

java.lang.IllegalArgumentException:属性[route]不是托管类型

路线

@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
}

路线

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

    @ManyToMany
    private List<Town> towns;

    // some getter and setter
}

1 个答案:

答案 0 :(得分:6)

看看Hibernate对org.hibernate.jpa.graph.internal.AttributeNodeImpl的实现,我们得出的结论是@NamedAttributeNode不能:

  • 简单类型(Java原语及其包装,字符串,枚举,时态,......)
  • embeddables(注释为@Embedded
  • 元素集合(使用@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())
    );
}

我没有在JPA 2.1规范中找到类似的限制,因此可能是Hibernate的缺点。


在您的特定情况下,问题是@NamedEntityGraph引用了Route类是可嵌入的,因此它在实体图中的使用似乎被Hibernate禁止(不幸的是)。

为了使其工作,您需要稍微更改您的实体模型。我想到了一些例子:

  • Route定义为实体
  • 删除Route并将其towns字段移至Ride实体(简化实体模型)
  • route字段从Ride移至Town实体,将routedTowns地图的地图添加到Ride实体:

    @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;
        ...
    }
    

当然,实体图可能需要相应的更改。