JPA Entity Graph.
This commit is contained in:
parent
9127733ad1
commit
64bc8a412d
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.jpa.entitygraph;
|
||||||
|
|
||||||
|
import com.baeldung.jpa.entitygraph.model.Post;
|
||||||
|
import com.baeldung.jpa.entitygraph.repo.PostRepository;
|
||||||
|
|
||||||
|
public class MainApp {
|
||||||
|
|
||||||
|
public static void main(String... args) {
|
||||||
|
Long postId = 1L;
|
||||||
|
Post post = null;
|
||||||
|
PostRepository postRepository = new PostRepository();
|
||||||
|
|
||||||
|
//Using EntityManager.find().
|
||||||
|
post = postRepository.find(postId);
|
||||||
|
post = postRepository.findWithEntityGraph(postId);
|
||||||
|
post = postRepository.findWithEntityGraph2(postId);
|
||||||
|
|
||||||
|
//Using JPQL: Query and TypedQuery
|
||||||
|
post = postRepository.findUsingJpql(postId);
|
||||||
|
|
||||||
|
//Using Criteria API
|
||||||
|
post = postRepository.findUsingCriteria(postId);
|
||||||
|
|
||||||
|
postRepository.clean();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.jpa.entitygraph.model;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Comment {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String reply;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn
|
||||||
|
private Post post;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn
|
||||||
|
private User user;
|
||||||
|
//...
|
||||||
|
|
||||||
|
public Comment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comment(String reply, Post post, User user) {
|
||||||
|
this.reply = reply;
|
||||||
|
this.post = post;
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReply() {
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReply(String reply) {
|
||||||
|
this.reply = reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post getPost() {
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPost(Post post) {
|
||||||
|
this.post = post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.baeldung.jpa.entitygraph.model;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@NamedEntityGraph(
|
||||||
|
name = "post-entity-graph",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode("subject"),
|
||||||
|
@NamedAttributeNode("user"),
|
||||||
|
@NamedAttributeNode("comments"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@NamedEntityGraph(
|
||||||
|
name = "post-entity-graph-with-comment-users",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode("subject"),
|
||||||
|
@NamedAttributeNode("user"),
|
||||||
|
@NamedAttributeNode(value = "comments", subgraph = "comments-subgraph"),
|
||||||
|
},
|
||||||
|
subgraphs = {
|
||||||
|
@NamedSubgraph(
|
||||||
|
name = "comments-subgraph",
|
||||||
|
attributeNodes = {
|
||||||
|
@NamedAttributeNode("user")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@Entity
|
||||||
|
public class Post {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
private String subject;
|
||||||
|
@OneToMany(mappedBy = "post")
|
||||||
|
private List<Comment> comments = new ArrayList<>();
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn
|
||||||
|
private User user;
|
||||||
|
//...
|
||||||
|
|
||||||
|
public Post() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post(String subject, User user) {
|
||||||
|
this.subject = subject;
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSubject() {
|
||||||
|
return subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Comment> getComments() {
|
||||||
|
return comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComments(List<Comment> comments) {
|
||||||
|
this.comments = comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.baeldung.jpa.entitygraph.model;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
//...
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.baeldung.jpa.entitygraph.repo;
|
||||||
|
|
||||||
|
import com.baeldung.jpa.entitygraph.model.Post;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class PostRepository {
|
||||||
|
private EntityManagerFactory emf = null;
|
||||||
|
|
||||||
|
|
||||||
|
public PostRepository() {
|
||||||
|
Map properties = new HashMap();
|
||||||
|
properties.put("hibernate.show_sql", "true");
|
||||||
|
properties.put("hibernate.format_sql", "true");
|
||||||
|
emf = Persistence.createEntityManagerFactory("entity-graph-pu", properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post find(Long id) {
|
||||||
|
EntityManager entityManager = emf.createEntityManager();
|
||||||
|
|
||||||
|
Post post = entityManager.find(Post.class, id);
|
||||||
|
|
||||||
|
entityManager.close();
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post findWithEntityGraph(Long id) {
|
||||||
|
EntityManager entityManager = emf.createEntityManager();
|
||||||
|
|
||||||
|
EntityGraph entityGraph = entityManager.getEntityGraph("post-entity-graph");
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put("javax.persistence.fetchgraph", entityGraph);
|
||||||
|
Post post = entityManager.find(Post.class, id, properties);
|
||||||
|
|
||||||
|
entityManager.close();
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post findWithEntityGraph2(Long id) {
|
||||||
|
EntityManager entityManager = emf.createEntityManager();
|
||||||
|
|
||||||
|
EntityGraph<Post> entityGraph = entityManager.createEntityGraph(Post.class);
|
||||||
|
entityGraph.addAttributeNodes("subject");
|
||||||
|
entityGraph.addAttributeNodes("user");
|
||||||
|
entityGraph.addSubgraph("comments")
|
||||||
|
.addAttributeNodes("user");
|
||||||
|
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put("javax.persistence.fetchgraph", entityGraph);
|
||||||
|
Post post = entityManager.find(Post.class, id, properties);
|
||||||
|
|
||||||
|
entityManager.close();
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post findUsingJpql(Long id) {
|
||||||
|
EntityManager entityManager = emf.createEntityManager();
|
||||||
|
|
||||||
|
EntityGraph entityGraph = entityManager.getEntityGraph("post-entity-graph-with-comment-users");
|
||||||
|
Post post = entityManager.createQuery("Select p from Post p where p.id=:id", Post.class)
|
||||||
|
.setParameter("id", id)
|
||||||
|
.setHint("javax.persistence.fetchgraph", entityGraph)
|
||||||
|
.getSingleResult();
|
||||||
|
|
||||||
|
entityManager.close();
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Post findUsingCriteria(Long id) {
|
||||||
|
EntityManager entityManager = emf.createEntityManager();
|
||||||
|
|
||||||
|
EntityGraph entityGraph = entityManager.getEntityGraph("post-entity-graph-with-comment-users");
|
||||||
|
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Post> criteriaQuery = criteriaBuilder.createQuery(Post.class);
|
||||||
|
Root<Post> root = criteriaQuery.from(Post.class);
|
||||||
|
criteriaQuery.where(criteriaBuilder.equal(root.<Long>get("id"), id));
|
||||||
|
TypedQuery<Post> typedQuery = entityManager.createQuery(criteriaQuery);
|
||||||
|
typedQuery.setHint("javax.persistence.loadgraph", entityGraph);
|
||||||
|
Post post = typedQuery.getSingleResult();
|
||||||
|
|
||||||
|
entityManager.close();
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clean() {
|
||||||
|
emf.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,12 +9,12 @@
|
||||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
<class>com.baeldung.sqlresultsetmapping.ScheduledDay</class>
|
<class>com.baeldung.sqlresultsetmapping.ScheduledDay</class>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
|
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
|
||||||
<property name="javax.persistence.jdbc.url"
|
<property name="javax.persistence.jdbc.url"
|
||||||
value="jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'classpath:database.sql'" />
|
value="jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'classpath:database.sql'"/>
|
||||||
<property name="javax.persistence.jdbc.user" value="sa" />
|
<property name="javax.persistence.jdbc.user" value="sa"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="" />
|
<property name="javax.persistence.jdbc.password" value=""/>
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||||
<!--<property name="hibernate.hbm2ddl.auto" value="create-drop" />-->
|
<!--<property name="hibernate.hbm2ddl.auto" value="create-drop" />-->
|
||||||
<property name="show_sql" value="true"/>
|
<property name="show_sql" value="true"/>
|
||||||
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
||||||
|
@ -25,28 +25,45 @@
|
||||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
<class>com.baeldung.jpa.stringcast.Message</class>
|
<class>com.baeldung.jpa.stringcast.Message</class>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
|
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test" />
|
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
|
||||||
<property name="javax.persistence.jdbc.user" value="sa" />
|
<property name="javax.persistence.jdbc.user" value="sa"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="" />
|
<property name="javax.persistence.jdbc.password" value=""/>
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||||
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
|
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||||
<property name="show_sql" value="true"/>
|
<property name="show_sql" value="true"/>
|
||||||
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
<persistence-unit name="jpa-db">
|
<persistence-unit name="jpa-db">
|
||||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
<class>com.baeldung.jpa.model.Car</class>
|
<class>com.baeldung.jpa.model.Car</class>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
|
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
|
||||||
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/baeldung" />
|
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/baeldung"/>
|
||||||
<property name="javax.persistence.jdbc.user" value="baeldung" />
|
<property name="javax.persistence.jdbc.user" value="baeldung"/>
|
||||||
<property name="javax.persistence.jdbc.password" value="YourPassword" />
|
<property name="javax.persistence.jdbc.password" value="YourPassword"/>
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
|
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
|
||||||
<property name="hibernate.show_sql" value="true" />
|
<property name="hibernate.show_sql" value="true"/>
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
|
<persistence-unit name="entity-graph-pu" transaction-type="RESOURCE_LOCAL">
|
||||||
|
<class>com.baeldung.jpa.entitygraph.model.Post</class>
|
||||||
|
<class>com.baeldung.jpa.entitygraph.model.User</class>
|
||||||
|
<class>com.baeldung.jpa.entitygraph.model.Comment</class>
|
||||||
|
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||||
|
<properties>
|
||||||
|
|
||||||
|
<!--H2-->
|
||||||
|
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
|
||||||
|
<property name="javax.persistence.jdbc.url"
|
||||||
|
value="jdbc:h2:mem:entitygraphdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"/>
|
||||||
|
|
||||||
|
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
|
||||||
|
<property name="javax.persistence.sql-load-script-source" value="data-init.sql"/>
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
|
|
||||||
</persistence>
|
</persistence>
|
|
@ -0,0 +1,8 @@
|
||||||
|
INSERT INTO `USER` (`ID`,`NAME`,`EMAIL`) VALUES (1,'user1','user1@test.com');
|
||||||
|
INSERT INTO `USER` (`ID`,`NAME`,`EMAIL`) VALUES (2,'user2','user2@test.com');
|
||||||
|
INSERT INTO `USER` (`ID`,`NAME`,`EMAIL`) VALUES (3,'user3','user3@test.com');
|
||||||
|
|
||||||
|
INSERT INTO `POST` (`ID`,`SUBJECT`,`USER_ID`) VALUES (1,'JPA Entity Graph In Action',1);
|
||||||
|
|
||||||
|
INSERT INTO `COMMENT` (`ID`,`REPLY`,`POST_ID`,`USER_ID`) VALUES (1,'Nice !!',1,2);
|
||||||
|
INSERT INTO `COMMENT` (`ID`,`REPLY`,`POST_ID`,`USER_ID`) VALUES (2,'Cool !!',1,3);
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.baeldung.jpa.entitygraph.repo;
|
||||||
|
|
||||||
|
import com.baeldung.jpa.entitygraph.model.Comment;
|
||||||
|
import com.baeldung.jpa.entitygraph.model.Post;
|
||||||
|
import com.baeldung.jpa.entitygraph.model.User;
|
||||||
|
import org.hibernate.LazyInitializationException;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PostRepositoryTest {
|
||||||
|
|
||||||
|
private static PostRepository postRepository = null;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void once() {
|
||||||
|
postRepository = new PostRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = LazyInitializationException.class)
|
||||||
|
public void find() {
|
||||||
|
Post post = postRepository.find(1L);
|
||||||
|
assertNotNull(post.getUser());
|
||||||
|
String email = post.getUser().getEmail();
|
||||||
|
assertNull(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findWithEntityGraph() {
|
||||||
|
Post post = postRepository.findWithEntityGraph(1L);
|
||||||
|
assertNotNull(post.getUser());
|
||||||
|
String email = post.getUser().getEmail();
|
||||||
|
assertNotNull(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = LazyInitializationException.class)
|
||||||
|
public void findWithEntityGraph_Comment_Without_User() {
|
||||||
|
Post post = postRepository.findWithEntityGraph(1L);
|
||||||
|
assertNotNull(post.getUser());
|
||||||
|
String email = post.getUser().getEmail();
|
||||||
|
assertNotNull(email);
|
||||||
|
assertNotNull(post.getComments());
|
||||||
|
assertEquals(post.getComments().size(), 2);
|
||||||
|
Comment comment = post.getComments().get(0);
|
||||||
|
assertNotNull(comment);
|
||||||
|
User user = comment.getUser();
|
||||||
|
user.getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void findWithEntityGraph2_Comment_With_User() {
|
||||||
|
Post post = postRepository.findWithEntityGraph2(1L);
|
||||||
|
assertNotNull(post.getComments());
|
||||||
|
assertEquals(post.getComments().size(), 2);
|
||||||
|
Comment comment = post.getComments().get(0);
|
||||||
|
assertNotNull(comment);
|
||||||
|
User user = comment.getUser();
|
||||||
|
assertNotNull(user);
|
||||||
|
assertEquals(user.getEmail(), "user2@test.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void destroy() {
|
||||||
|
postRepository.clean();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue