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);
}
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=?
)
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=?
So, what I'm doing wrong? Does this feature is not supported by Hibernate??
NOTE: For the test, I was using hibernate 5.0.10 and wildfly10 ...
Thanks!
You can create entity graphs statically by using annotations or a deployment descriptor, or dynamically by using standard interfaces. You can use an entity graph with the EntityManager. find method or as part of a JPQL or Criteria API query by specifying the entity graph as a hint to the operation or query.
Simply put, Entity Graphs are another way to describe a query in JPA 2.1. We can use them to formulate better-performing queries. In this tutorial, we're going to learn how to implement Entity Graphs with Spring Data JPA through a simple example.
The @NamedEntityGraph annotation allows specifying the attributes to include when we want to load the entity and the related associations. In this example, we've used the @NamedAttributeNode to define the related entities to be loaded when the root entity is loaded.
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 (defaults toEAGER
)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.
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.
Side notes: I checked..
The persistence provider is permitted to fetch additional entity state beyond that specified by a fetch graph or load graph.
The latter quote from the JPA-spec backs the ORM User Guide that this it is ok to implement it that way.
My advice:
Look into BytecodeEnhancement as stated by the Hibernate ORM User Guide (see above).
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With