如何使用JPA-EntityGraph仅加载实体@Basic属性的子集? [英] How to use JPA - EntityGraph to load only a subset of entity @Basic attributes?

查看:165
本文介绍了如何使用JPA-EntityGraph仅加载实体@Basic属性的子集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了关于实体图的文档. ..阅读完之后,它给了我一个想法,您可以使用实体图来检索给定实体的@Basic字段的子集(直到现在,我已经使用实体图来检索EAGERLY关系,例如,对于例如,加载一个Employee [包括所有属性]及其关联的Department [包括所有属性])...

I found this documentation about entity-graphs... after read it, it gave me the idea that you can used entity-graphs to retrieve only a subset of @Basic fields of a given entity (Until now, I have used entity-graphs to retrieve relationships EAGERLY, i.e, for example, load an Employee[including all its attributes] and its associated Department[including all its attributes])...

因此,我决定使用一个小测试来尝试此操作:

So, I decided to try this using a small test:

@Entity
@Table(name = "employee")
@NamedEntityGraphs({
    @NamedEntityGraph(
        name = "OnlyName",
        attributeNodes = @NamedAttributeNode(value = "name")
    )
})
public class Employee implements Serializable {
    ...
    @Id
    @Column(name = "code", updatable = false)
    private Long code;

    @Basic(fetch = FetchType.LAZY)
    @Column(name = "name", nullable = false)
    private String name;

    @Basic(fetch = FetchType.LAZY)
    @Column(name = "last_name", nullable = false)
    private String lastName;

    @Lob @Basic(fetch = FetchType.LAZY)
    @Column(name = "picture", nullable = false)
    private byte[] picture;

    public Employee() {
       super();
    }
    ...
}

然后,使用以下代码检索我的实体:

Then, to retrieve my entity, I used the following code:

    private Employee retrieveFromDatabase(long code) {
        EntityGraph<Employee> graph;                // Material Entity Graph

        Map<String, Object> map = new HashMap<>();

        graph = (EntityGraph<Employee>) this.em.createEntityGraph("OnlyName");
        map.put("javax.persistence.fetchgraph", graph);


        return this.em.find(Employee.class, code, map);
    }

现在,此代码将始终返回一个Employee,其中包含从数据库中获取的所有字段.甚至Hibernate日志也显示一个查询,该查询选择了所有员工字段:

Now, this code always returns an Employee with all the fields fetched from the database; even the Hibernate logs show a query that selects all employee fields:

Hibernate: select employee0_.code as code1_0_0_, employee0_.last_name as last_name2_0_0_, employee0_.name as name3_0_0_, employee0_.picture as picture4_0_0_ from employee employee0_ where employee0_.code=? )

Hibernate: select employee0_.code as code1_0_0_, employee0_.last_name as last_name2_0_0_, employee0_.name as name3_0_0_, employee0_.picture as picture4_0_0_ from employee employee0_ where employee0_.code=? )

当我期望这样的查询时:select employee0_.code as code1_0_0_, mployee0_.name as name3_0_0_ from employee employee0_ where employee0_.code=?

When I was expecting a query like this: select employee0_.code as code1_0_0_, mployee0_.name as name3_0_0_ from employee employee0_ where employee0_.code=?

那么,我做错了什么? Hibernate是否不支持?

So, what I'm doing wrong? Does this feature is not supported by Hibernate??

注意:对于测试,我使用的是休眠5.0.10和wildfly10 ...

NOTE: For the test, I was using hibernate 5.0.10 and wildfly10 ...

谢谢!

推荐答案

实际上,您没有做错任何事情.但是,您从

Actually, you are not doing anything wrong. Yet, you are missing an important piece of information from the Hibernate ORM User Guide (v5.0.x). In section 2.3.2 we find it:

fetch-FetchType(默认为EAGER)

fetch - FetchType (defaults to EAGER)

定义此属性是应立即获取还是应延迟获取. JPA表示,EAGER是提供程序(休眠)的要求,即在提取所有者时应提取值,而LAZY只是提示在访问属性时要提取值. Hibernate忽略基本类型的此设置,除非您使用字节码增强功能.有关获取其他信息,请参见 BytecodeEnhancement 以及字节码增强.

Defines whether this attribute should be fetched eagerly or lazily. JPA says that EAGER is a requirement to the provider (Hibernate) that the value should be fetched when the owner is fetched, while LAZY is merely a hint that the value be fetched when the attribute is accessed. Hibernate ignores this setting for basic types unless you are using bytecode enhancement. See the BytecodeEnhancement for additional information on fetching and on bytecode enhancement.

因此:即使您向em.find(..)方法提供查询提示,也取决于JPA提供程序-在这里:休眠-决定是否急切地获取基本属性.在您的情况下,Employee实体仅包含@Basic属性.

So: Even though you are giving a query hint to the em.find(..) method, it's up to the JPA provider - here: Hibernate - to decide if basic attributes will be fetched eagerly or not. In your case, the Employee entity only contains @Basic attributes.

作为参考,以及更多背景信息和更详细的解释,另请参见此

For reference, and for a more context as well as a more detailed explanation, see also this tutorial. It covers differences between "javax.persistence.fetchgraph" and "javax.persistence.loadgraph"query hints and has example code which demonstrates the above behaviour for the JPA persistence provider Hibernate.

旁注:我检查了.

  • .. the Hibernate ORM User Guides 5.1, 5.2, and 5.3: All versions contain the very same statement on the default policy to ignore basic attributes.
  • .. the official JPA 2.1 specification document. On (PDF) page 117, in Section 3.7.4 we find:

允许持久性提供程序获取由获取图或负载图指定的超出的其他实体状态.

JPA规范中的后一个引用支持 ORM用户指南,可以这样实现.

The latter quote from the JPA-spec backs the ORM User Guide that this it is ok to implement it that way.

我的建议:

按照《 Hibernate ORM用户指南》(请参见上文)中的说明 BytecodeEnhancement .

Look into BytecodeEnhancement as stated by the Hibernate ORM User Guide (see above).

希望有帮助.

这篇关于如何使用JPA-EntityGraph仅加载实体@Basic属性的子集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆