JPA 2.1 Eager Fetch 属性

Posted

技术标签:

【中文标题】JPA 2.1 Eager Fetch 属性【英文标题】:JPA 2.1 Eager Fetch Attribute 【发布时间】:2014-04-09 08:00:45 【问题描述】:

我有一个属性(元数据中的creationTimestamp),我将其注释为延迟加载。不,我需要一个实体来加载渴望。我尝试使用获取图表但没有成功。是否有类似 JOIN FETCH 的功能可以用来在查询中获取它?

我将 Wildfly 与捆绑的休眠一起使用。

当我尝试使用 fetch graph 获取它时,我得到了 hibernate 找不到 id 字段的异常。此字段在实体库中(受保护)。

@NamedQueries( @NamedQuery(name = ChatMessage.FIND_BY_CHAT_TIME, query = "SELECT m FROM ChatMessage m "
        + "WHERE m.chat=:chat "
        + "AND m.creationTimestamp > :index ORDER BY m.creationTimestamp") )
@NamedEntityGraph(
        name = ChatMessage.GRAPH_FETCH_ALL,
        attributeNodes = @NamedAttributeNode("id"), @NamedAttributeNode("player"), @NamedAttributeNode("text"), @NamedAttributeNode("creationTimestamp")
    )
public class ChatMessage extends EntityBase 

@MappedSuperclass
public abstract class EntityBase extends MetaData 
    private static final long serialVersionUID = -5579667581450362176L;

    public static final String FETCH_GRAPH_HINT = "javax.persistence.fetchgraph";

    @Id
    @Column(length = 36)
    protected String id = java.util.UUID.randomUUID().toString();

@MappedSuperclass
public class MetaData implements Serializable 
    private static final long serialVersionUID = 8870539357817188030L;

    @Version
    private long version;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false, updatable = false)
    @Basic(fetch=FetchType.LAZY)
    protected Calendar creationTimestamp;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable = false)
    @Basic(fetch=FetchType.LAZY)
    private Calendar updateTimestamp;

导致此异常:

Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [id] on this ManagedType [ChatMessage]
    at org.hibernate.jpa.internal.metamodel.AbstractManagedType.checkNotNull(AbstractManagedType.java:144)
    at org.hibernate.jpa.internal.metamodel.AbstractManagedType.getDeclaredAttribute(AbstractManagedType.java:137)
    at org.hibernate.jpa.graph.internal.EntityGraphImpl.resolveAttribute(EntityGraphImpl.java:139)
    at org.hibernate.jpa.graph.internal.AbstractGraphNode.buildAttributeNode(AbstractGraphNode.java:119)
    at org.hibernate.jpa.graph.internal.AbstractGraphNode.addAttribute(AbstractGraphNode.java:114)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.applyNamedAttributeNodes(EntityManagerFactoryImpl.java:279)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.applyNamedEntityGraphs(EntityManagerFactoryImpl.java:266)
    at org.hibernate.jpa.internal.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:173)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:865)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:73)

有没有办法像 fetch join 一样获取属性?还是我必须以其他方式引用获取图?

最好的问候, 米

【问题讨论】:

【参考方案1】:

看起来子类的属性必须以不同的方式引用:

@NamedEntityGraph(
        name = ChatMessage.GRAPH_FETCH_ALL,
        attributeNodes = @NamedAttributeNode("player"), @NamedAttributeNode("text")
        , subgraphs=@NamedSubgraph(name="MetaData.subgraph", attributeNodes=@NamedAttributeNode("id"), @NamedAttributeNode("creationTimestamp"))
    )

【讨论】:

以上是关于JPA 2.1 Eager Fetch 属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 JPA 在 Hibernate 中使用 EAGER 类型进行多次提取

Spring Data JPA 检查 SET 是不是包含对象

JPA数据懒加载LAZY和实时加载EAGER(转)

hibernate FetchType理解

使用 JPA Criteria API,你能做一个只导致一个连接的 fetch join 吗?

JPA 2.1 属性转换器转换枚举仍然插入 int