跳至主要内容

JPA 2.1: Entity Graph


JPA 2.1: Entity Graph

Entity Graph is a means to specify the structure of a graph of entities, it defines the return path and boundaries when the entity is loaded.

Define Entity Graph

You can define an Entity graph via @NamedEntityGraph annotation.
@NamedEntityGraph(
        name = "post",
        attributeNodes = {
            @NamedAttributeNode("title"),
            @NamedAttributeNode(value = "comments", subgraph = "comments")
        },
        subgraphs = {
            @NamedSubgraph(
                    name = "comments",
                    attributeNodes = {
                        @NamedAttributeNode("content")}
            )
        }
)
or create a EntityGraph dynamically via createEntitGraph method of EntityManager.
EntityGraph postEntityGraph=em.createEntityGraph(Post.class);
postEntityGraph.addAttributeNodes("title");
postEntityGraph.addSubgraph("comments").addAttributeNodes("content");

Apply the Entity Graph

Get the EntityGraph.
EntityGraph postGraph=em.getEntityGraph("post");
Set the value of javax.persistence.fetchgraph
em.createQuery("select p from Post p where p.id=:id", Post.class)
  .setHint("javax.persistence.fetchgraph", postGraph)
  .setParameter("id", this.id)
  .getResultList()
  .get(0);
There are two hints available in JPA 2.1 for configuring the Entity Graph loading strategy.
javax.persistence.fetchgraph will load all attributes defined in the EntityGraph, and all unlisted attributes will use LAZY to load.
javax.persistence.loadgraph will load all attributes defined in the EntityGraph, and all unlisted attributes will apply it's fetch settings.

What problem it resolved

If you are using Hibernate, you have to encounter the famous LazyInitializedExcpetion when you try to fetch values from association attributes of an entity outside of an active Session.
There are some existed solutions to resolve this problem. In a web application, most of case, this exception could be thrown in the view layer, one solution is introduce Open Session in View pattern, in Spring application, an OpenInView AOP Interceptor(for none web application) and an OpenInView web Filter(for web application) are provided.
Now, the Entity Graph could be another robust solution for resolving this issue. For those cases which require to hint the lazy association of an Entity, create a Entity Graph to load them when the query is executed.
Some JPA providers, such as OpenJPA, provide a Fetch Plan feature, which is similar with the Entity Graph.

Summary

The Entity Graph overrides the default loading strategy, and provides flexibility of loading the association attributes of an Entity.
The sample codes are hosted on my github.com account, check out and play it yourself.

评论

此博客中的热门博文

Build a Reactive application with Angular 5 and Spring Boot 2.0

I have created a post to describe Reactive programming supports in Spring 5 and its subprojects, all codes of this article are updated the latest Spring 5 RELEASE, check spring-reactive-sample under my Github account.
In this post, I will create a simple blog system, including:
A user can sign in and sign out.An authenticated user can create a post.An authenticated user can update a post.Only the user who has ADMIN role can delete a post.All users(including anonymous users) can view post list and post details.An authenticated user can add his comments to a certain post. The backend will be built with the latest Spring 5 reactive stack, including:
Spring Boot 2.0, at the moment the latest version is 2.0.0.M7Spring Data MongoDB supports reactive operations for MongoDBSpring Session adds reactive support for WebSessionSpring Security 5 aligns with Spring 5 reactive stack The frontend is an Angular based SPA and it will be generated by Angular CLI.
The source code is hosted on Github, …

Activating CDI in JSF 2.3

Activating CDI in JSF 2.3 When I upgraed my Java EE 7 sample to the newest Java EE 8, the first thing confused me is the CDI beans are not recoganized in Facelects template in a JSF 2.3 based web applicaiton, which is working in the development version, but in the final release version, they are always resolved as null. I filed an issue on Mojarra and discussed it with the developers from communities and the JSF experts.
According to the content of README, In a JSF 2.3 application, to activate CDI support, declaring a 2.3 versioned faces-config.xml and adding javax.faces.ENABLE_CDI_RESOLVER_CHAIN in web.xml is not enough, you have to declare @FacesConfig annotated class to enable CDI.
Here is the steps I created a workable JSF 2.3 applicatoin in Java EE 8.
Create a Java web application, this can be done easily by NetBeans IDE, or generated by Maven archetype, for exmaple.
$ mvn archetype:generate -DgroupId=com.example -DartifactId=demo -DarchetypeArtifactId=maven-archetype-w…

JSF 2.3:Websocket support

Websocket support One of the most attractive features is JSF 2.3 added native websocket support, it means you can write real-time applications with JSF and no need extra effort.
To enable websocket support, you have to add javax.faces.ENABLE_WEBSOCKET_ENDPOINT in web.xml.
<context-param> <param-name>javax.faces.ENABLE_WEBSOCKET_ENDPOINT</param-name> <param-value>true</param-value> </context-param> Hello Websocket Let's start with a simple example.
@ViewScoped@Named("helloBean") publicclassHelloBeanimplementsSerializable { privatestaticfinalLoggerLOG=Logger.getLogger(HelloBean.class.getName()); @Inject@PushPushContext helloChannel; String message; publicvoidsendMessage() { LOG.log(Level.INFO, "send push message"); this.sendPushMessage("hello"); } privatevoidsendPushMessage(Objectmessage) { helloChannel.send(""+ message +" at &…