Merge pull request #5764 from eelhazati/master
BAEL-2395: JPA Entity Graph.
This commit is contained in:
commit
eaeed72a98
|
@ -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>
|
||||
<class>com.baeldung.sqlresultsetmapping.ScheduledDay</class>
|
||||
<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;INIT=RUNSCRIPT FROM 'classpath:database.sql'" />
|
||||
<property name="javax.persistence.jdbc.user" value="sa" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
||||
value="jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'classpath:database.sql'"/>
|
||||
<property name="javax.persistence.jdbc.user" value="sa"/>
|
||||
<property name="javax.persistence.jdbc.password" value=""/>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||
<!--<property name="hibernate.hbm2ddl.auto" value="create-drop" />-->
|
||||
<property name="show_sql" value="true"/>
|
||||
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
||||
|
@ -25,28 +25,45 @@
|
|||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||
<class>com.baeldung.jpa.stringcast.Message</class>
|
||||
<properties>
|
||||
<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.user" value="sa" />
|
||||
<property name="javax.persistence.jdbc.password" value="" />
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
|
||||
<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.user" value="sa"/>
|
||||
<property name="javax.persistence.jdbc.password" value=""/>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
|
||||
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
|
||||
<property name="show_sql" value="true"/>
|
||||
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
|
||||
<persistence-unit name="jpa-db">
|
||||
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||
<class>com.baeldung.jpa.model.Car</class>
|
||||
<properties>
|
||||
<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.user" value="baeldung" />
|
||||
<property name="javax.persistence.jdbc.password" value="YourPassword" />
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
|
||||
<property name="hibernate.show_sql" value="true" />
|
||||
<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.user" value="baeldung"/>
|
||||
<property name="javax.persistence.jdbc.password" value="YourPassword"/>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
|
||||
<property name="hibernate.show_sql" value="true"/>
|
||||
</properties>
|
||||
</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>
|
|
@ -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 PostRepositoryIntegrationTest {
|
||||
|
||||
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