├── .gitignore ├── README.md ├── pom.xml └── src └── main ├── java └── com │ └── softwarehut │ └── jpa │ └── entityGraph │ ├── Application.java │ ├── CompanyController.java │ ├── model │ ├── Address.java │ ├── Car.java │ ├── Company.java │ ├── Department.java │ ├── Employee.java │ └── Office.java │ └── service │ ├── CompanyService.java │ ├── CompanyServiceCriteriaAPIImpl.java │ ├── CompanyServiceEntityGraphImpl.java │ └── CompanyServiceNamedQueryImpl.java └── resources ├── application.properties └── db └── migration └── h2 ├── V1__create_address.sql ├── V2__create_car.sql ├── V3__create_company.sql ├── V4__create_department.sql ├── V5__create_employee.sql ├── V6__insert_car.sql ├── V7__create_office.sql └── V8__insert_office.sql /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .idea/ 3 | *.class 4 | *.iml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EntityGraph 2 | 3 | [![Issue Count](https://codeclimate.com/github/adamzareba/EntityGraph/badges/issue_count.svg)](https://codeclimate.com/github/adamzareba/EntityGraph) 4 | 5 | Example project for Spring Boot that uses JPA/Hibernate for querying data from database, exposed REST API that returns data querying for data structure: 6 | 7 | ![database-schema](http://softwarehut.com/wp-content/uploads/2017/06/database-schema.png) 8 | 9 | Project demonstrates three different approaches for database querying: 10 | 1. Criteria API 11 | 2. Named Query 12 | 3. Named Entity Graph 13 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | entity-graph-jpa 8 | com.softwarehut 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 1.5.2.RELEASE 15 | 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-web 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-jpa 25 | 26 | 27 | org.hibernate 28 | hibernate-jpamodelgen 29 | 5.2.9.Final 30 | 31 | 32 | com.h2database 33 | h2 34 | 35 | 36 | org.flywaydb 37 | flyway-core 38 | 4.1.2 39 | 40 | 41 | com.fasterxml.jackson.datatype 42 | jackson-datatype-hibernate5 43 | 2.8.7 44 | 45 | 46 | org.projectlombok 47 | lombok 48 | 1.16.16 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | 57 | 58 | 1.8 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-maven-plugin 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-compiler-plugin 70 | 3.5.1 71 | 72 | 1.8 73 | 1.8 74 | 75 | true 76 | true 77 | 78 | org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/Application.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph; 2 | 3 | import com.fasterxml.jackson.databind.Module; 4 | import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; 5 | 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | @SpringBootApplication 11 | public class Application { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(Application.class, args); 15 | } 16 | 17 | @Bean 18 | public Module hibernate5Module() { 19 | return new Hibernate5Module(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/CompanyController.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph; 2 | 3 | import com.softwarehut.jpa.entityGraph.model.Company; 4 | import com.softwarehut.jpa.entityGraph.service.CompanyService; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Qualifier; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | import org.springframework.web.bind.annotation.ResponseStatus; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | @RestController 17 | @RequestMapping("/company/") 18 | public class CompanyController { 19 | 20 | @Autowired 21 | @Qualifier(value = "companyServiceEntityGraph") 22 | private CompanyService companyService; 23 | 24 | @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/withDepartments/{companyId}") 25 | @ResponseStatus(value = HttpStatus.OK) 26 | public Company getCompanyWithDepartments(@PathVariable("companyId") Long companyId) { 27 | return companyService.getCompanyWithDepartments(companyId); 28 | } 29 | 30 | @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/withDepartmentsAndEmployees/{companyId}") 31 | @ResponseStatus(value = HttpStatus.OK) 32 | public Company getCompanyWithDepartmentsAndEmployees(@PathVariable("companyId") Long companyId) { 33 | return companyService.getCompanyWithDepartmentsAndEmployees(companyId); 34 | } 35 | 36 | @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/withDepartmentsAndEmployeesAndOffices/{companyId}") 37 | @ResponseStatus(value = HttpStatus.OK) 38 | public Company getCompanyWithDepartmentsAndEmployeesAndOffices(@PathVariable("companyId") Long companyId) { 39 | return companyService.getCompanyWithDepartmentsAndEmployeesAndOffices(companyId); 40 | } 41 | 42 | @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE, path = "/withCars/{companyId}") 43 | @ResponseStatus(value = HttpStatus.OK) 44 | public Company getCompanyWithCars(@PathVariable("companyId") Long companyId) { 45 | return companyService.getCompanyWithCars(companyId); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Address.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | 11 | import lombok.Getter; 12 | import lombok.Setter; 13 | 14 | @Entity 15 | @Getter 16 | @Setter 17 | public class Address implements Serializable { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.AUTO) 21 | @Column(name = "id", updatable = false, nullable = false) 22 | private Long id = null; 23 | 24 | private String street; 25 | 26 | private String houseNumber; 27 | 28 | private String zipCode; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Car.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | 5 | import java.io.Serializable; 6 | 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.FetchType; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.ManyToOne; 14 | 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | 18 | @Entity 19 | @Getter 20 | @Setter 21 | public class Car implements Serializable { 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.AUTO) 25 | @Column(name = "id", updatable = false, nullable = false) 26 | private Long id = null; 27 | 28 | private String registrationNumber; 29 | 30 | @ManyToOne(fetch = FetchType.LAZY) 31 | @JsonBackReference 32 | private Company company; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Company.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonManagedReference; 4 | 5 | import java.io.Serializable; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.FetchType; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.GenerationType; 14 | import javax.persistence.Id; 15 | import javax.persistence.NamedAttributeNode; 16 | import javax.persistence.NamedEntityGraph; 17 | import javax.persistence.NamedEntityGraphs; 18 | import javax.persistence.NamedNativeQueries; 19 | import javax.persistence.NamedNativeQuery; 20 | import javax.persistence.NamedQueries; 21 | import javax.persistence.NamedQuery; 22 | import javax.persistence.NamedSubgraph; 23 | import javax.persistence.OneToMany; 24 | 25 | import lombok.Getter; 26 | import lombok.Setter; 27 | 28 | @Entity 29 | @NamedQueries({ 30 | @NamedQuery(name = "companyWithDepartmentsNamedQuery", 31 | query = "SELECT DISTINCT c " + 32 | "FROM Company c " + 33 | "LEFT JOIN FETCH c.departments " + 34 | "WHERE c.id = :id"), 35 | @NamedQuery(name = "companyWithDepartmentsAndEmployeesNamedQuery", 36 | query = "SELECT DISTINCT c " + 37 | "FROM Company c " + 38 | "LEFT JOIN FETCH c.departments as d " + 39 | "LEFT JOIN FETCH d.employees " + 40 | "WHERE c.id = :id"), 41 | @NamedQuery(name = "companyWithDepartmentsAndEmployeesAndOfficesNamedQuery", 42 | query = "SELECT DISTINCT c " + 43 | "FROM Company c " + 44 | "LEFT JOIN FETCH c.departments as d " + 45 | "LEFT JOIN FETCH d.employees " + 46 | "LEFT JOIN FETCH d.offices " + 47 | "WHERE c.id = :id"), 48 | @NamedQuery(name = "companyWithCarsNamedQuery", 49 | query = "SELECT DISTINCT c " + 50 | "FROM Company c " + 51 | "LEFT JOIN FETCH c.cars " + 52 | "WHERE c.id = :id"), 53 | }) 54 | @NamedEntityGraphs({ 55 | @NamedEntityGraph(name = "companyWithDepartmentsGraph", 56 | attributeNodes = {@NamedAttributeNode("departments")}), 57 | @NamedEntityGraph(name = "companyWithDepartmentsAndEmployeesGraph", 58 | attributeNodes = {@NamedAttributeNode(value = "departments", subgraph = "departmentsWithEmployees")}, 59 | subgraphs = @NamedSubgraph( 60 | name = "departmentsWithEmployees", 61 | attributeNodes = @NamedAttributeNode("employees"))), 62 | @NamedEntityGraph(name = "companyWithDepartmentsAndEmployeesAndOfficesGraph", 63 | attributeNodes = {@NamedAttributeNode(value = "departments", subgraph = "departmentsWithEmployeesAndOffices")}, 64 | subgraphs = @NamedSubgraph( 65 | name = "departmentsWithEmployeesAndOffices", 66 | attributeNodes = {@NamedAttributeNode("employees"), @NamedAttributeNode("offices")})) 67 | }) 68 | @Getter 69 | @Setter 70 | public class Company implements Serializable { 71 | 72 | @Id 73 | @GeneratedValue(strategy = GenerationType.AUTO) 74 | @Column(name = "id", updatable = false, nullable = false) 75 | private Long id = null; 76 | 77 | private String name; 78 | 79 | @OneToMany(mappedBy = "company", fetch = FetchType.LAZY) 80 | @JsonManagedReference 81 | private Set departments = new HashSet<>(); 82 | 83 | @OneToMany(mappedBy = "company", fetch = FetchType.LAZY) 84 | @JsonManagedReference 85 | private Set cars = new HashSet<>(); 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Department.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | import com.fasterxml.jackson.annotation.JsonManagedReference; 5 | 6 | import java.io.Serializable; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.FetchType; 13 | import javax.persistence.GeneratedValue; 14 | import javax.persistence.GenerationType; 15 | import javax.persistence.Id; 16 | import javax.persistence.ManyToOne; 17 | import javax.persistence.OneToMany; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | 22 | @Entity 23 | @Getter 24 | @Setter 25 | public class Department implements Serializable { 26 | 27 | @Id 28 | @GeneratedValue(strategy = GenerationType.AUTO) 29 | @Column(name = "id", updatable = false, nullable = false) 30 | private Long id = null; 31 | 32 | private String name; 33 | 34 | @OneToMany(mappedBy = "department", fetch = FetchType.LAZY) 35 | @JsonManagedReference 36 | private Set employees = new HashSet<>(); 37 | 38 | @OneToMany(mappedBy = "department", fetch = FetchType.LAZY) 39 | @JsonManagedReference 40 | private Set offices = new HashSet<>(); 41 | 42 | @ManyToOne(fetch = FetchType.LAZY) 43 | @JsonBackReference 44 | private Company company; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Employee.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | 5 | import java.io.Serializable; 6 | 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.FetchType; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.NamedAttributeNode; 16 | import javax.persistence.NamedEntityGraph; 17 | import javax.persistence.NamedEntityGraphs; 18 | import javax.persistence.NamedSubgraph; 19 | import javax.persistence.OneToOne; 20 | 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | 24 | @Entity 25 | @Getter 26 | @Setter 27 | public class Employee implements Serializable { 28 | 29 | @Id 30 | @GeneratedValue(strategy = GenerationType.AUTO) 31 | @Column(name = "id", updatable = false, nullable = false) 32 | private Long id = null; 33 | 34 | private String name; 35 | 36 | private String surname; 37 | 38 | @OneToOne(fetch = FetchType.LAZY) 39 | @JoinColumn(name = "address_id") 40 | private Address address; 41 | 42 | @ManyToOne(fetch = FetchType.LAZY) 43 | @JsonBackReference 44 | private Department department; 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/model/Office.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonBackReference; 4 | 5 | import java.io.Serializable; 6 | 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.FetchType; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.JoinColumn; 14 | import javax.persistence.ManyToOne; 15 | import javax.persistence.OneToOne; 16 | 17 | import lombok.Getter; 18 | import lombok.Setter; 19 | 20 | @Entity 21 | @Getter 22 | @Setter 23 | public class Office implements Serializable { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.AUTO) 27 | @Column(name = "id", updatable = false, nullable = false) 28 | private Long id = null; 29 | 30 | private String name; 31 | 32 | @OneToOne(fetch = FetchType.LAZY) 33 | @JoinColumn(name = "address_id") 34 | private Address address; 35 | 36 | @ManyToOne(fetch = FetchType.LAZY) 37 | @JsonBackReference 38 | private Department department; 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/service/CompanyService.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.service; 2 | 3 | import com.softwarehut.jpa.entityGraph.model.Company; 4 | 5 | public interface CompanyService { 6 | 7 | Company getCompanyWithDepartments(Long companyId); 8 | 9 | Company getCompanyWithDepartmentsAndEmployees(Long companyId); 10 | 11 | Company getCompanyWithDepartmentsAndEmployeesAndOffices(Long companyId); 12 | 13 | Company getCompanyWithCars(Long companyId); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/service/CompanyServiceCriteriaAPIImpl.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.service; 2 | 3 | import com.softwarehut.jpa.entityGraph.model.Company; 4 | import com.softwarehut.jpa.entityGraph.model.Company_; 5 | import com.softwarehut.jpa.entityGraph.model.Department; 6 | import com.softwarehut.jpa.entityGraph.model.Department_; 7 | 8 | import org.springframework.dao.support.DataAccessUtils; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.persistence.EntityManager; 12 | import javax.persistence.PersistenceContext; 13 | import javax.persistence.criteria.CriteriaBuilder; 14 | import javax.persistence.criteria.CriteriaQuery; 15 | import javax.persistence.criteria.Fetch; 16 | import javax.persistence.criteria.JoinType; 17 | import javax.persistence.criteria.Predicate; 18 | import javax.persistence.criteria.Root; 19 | 20 | @Service(value = "companyServiceCriteriaAPI") 21 | public class CompanyServiceCriteriaAPIImpl implements CompanyService { 22 | 23 | @PersistenceContext 24 | private EntityManager entityManager; 25 | 26 | @Override 27 | public Company getCompanyWithDepartments(Long companyId) { 28 | CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 29 | CriteriaQuery query = builder.createQuery(Company.class); 30 | 31 | Root root = query.from(Company.class); 32 | root.fetch(Company_.departments, JoinType.LEFT); 33 | 34 | query.select(root).distinct(true); 35 | Predicate idPredicate = builder.equal(root.get(Company_.id), companyId); 36 | query.where(builder.and(idPredicate)); 37 | 38 | return DataAccessUtils.singleResult(entityManager.createQuery(query).getResultList()); 39 | } 40 | 41 | @Override 42 | public Company getCompanyWithDepartmentsAndEmployees(Long companyId) { 43 | CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 44 | CriteriaQuery query = builder.createQuery(Company.class); 45 | 46 | Root root = query.from(Company.class); 47 | Fetch departmentFetch = root.fetch(Company_.departments, JoinType.LEFT); 48 | departmentFetch.fetch(Department_.employees, JoinType.LEFT); 49 | 50 | query.select(root).distinct(true); 51 | Predicate idPredicate = builder.equal(root.get(Company_.id), companyId); 52 | query.where(builder.and(idPredicate)); 53 | 54 | return DataAccessUtils.singleResult(entityManager.createQuery(query).getResultList()); 55 | } 56 | 57 | @Override 58 | public Company getCompanyWithDepartmentsAndEmployeesAndOffices(Long companyId) { 59 | CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 60 | CriteriaQuery query = builder.createQuery(Company.class); 61 | 62 | Root root = query.from(Company.class); 63 | Fetch departmentFetch = root.fetch(Company_.departments, JoinType.LEFT); 64 | departmentFetch.fetch(Department_.employees, JoinType.LEFT); 65 | departmentFetch.fetch(Department_.offices, JoinType.LEFT); 66 | 67 | query.select(root).distinct(true); 68 | Predicate idPredicate = builder.equal(root.get(Company_.id), companyId); 69 | query.where(builder.and(idPredicate)); 70 | 71 | return DataAccessUtils.singleResult(entityManager.createQuery(query).getResultList()); 72 | } 73 | 74 | @Override 75 | public Company getCompanyWithCars(Long companyId) { 76 | CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 77 | CriteriaQuery query = builder.createQuery(Company.class); 78 | 79 | Root root = query.from(Company.class); 80 | root.fetch(Company_.cars, JoinType.LEFT); 81 | 82 | query.select(root).distinct(true); 83 | Predicate idPredicate = builder.equal(root.get(Company_.id), companyId); 84 | query.where(builder.and(idPredicate)); 85 | 86 | return DataAccessUtils.singleResult(entityManager.createQuery(query).getResultList()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/service/CompanyServiceEntityGraphImpl.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.service; 2 | 3 | import com.softwarehut.jpa.entityGraph.model.Company; 4 | 5 | import org.springframework.stereotype.Service; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import javax.persistence.EntityGraph; 11 | import javax.persistence.EntityManager; 12 | import javax.persistence.PersistenceContext; 13 | 14 | @Service(value = "companyServiceEntityGraph") 15 | public class CompanyServiceEntityGraphImpl implements CompanyService { 16 | 17 | @PersistenceContext 18 | private EntityManager entityManager; 19 | 20 | @Override 21 | public Company getCompanyWithDepartments(Long companyId) { 22 | EntityGraph graph = entityManager.getEntityGraph("companyWithDepartmentsGraph"); 23 | Map hints = new HashMap<>(); 24 | hints.put("javax.persistence.fetchgraph", graph); 25 | 26 | return entityManager.find(Company.class, companyId, hints); 27 | } 28 | 29 | @Override 30 | public Company getCompanyWithDepartmentsAndEmployees(Long companyId) { 31 | EntityGraph graph = entityManager.getEntityGraph("companyWithDepartmentsAndEmployeesGraph"); 32 | Map hints = new HashMap<>(); 33 | hints.put("javax.persistence.fetchgraph", graph); 34 | 35 | return entityManager.find(Company.class, companyId, hints); 36 | } 37 | 38 | @Override 39 | public Company getCompanyWithDepartmentsAndEmployeesAndOffices(Long companyId) { 40 | EntityGraph graph = entityManager.getEntityGraph("companyWithDepartmentsAndEmployeesAndOfficesGraph"); 41 | Map hints = new HashMap<>(); 42 | hints.put("javax.persistence.fetchgraph", graph); 43 | 44 | return entityManager.find(Company.class, companyId, hints); 45 | } 46 | 47 | @Override 48 | public Company getCompanyWithCars(Long companyId) { 49 | EntityGraph graph = entityManager.createEntityGraph(Company.class); 50 | graph.addAttributeNodes("cars"); 51 | 52 | Map hints = new HashMap<>(); 53 | hints.put("javax.persistence.loadgraph", graph); 54 | 55 | return entityManager.find(Company.class, companyId, hints); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/softwarehut/jpa/entityGraph/service/CompanyServiceNamedQueryImpl.java: -------------------------------------------------------------------------------- 1 | package com.softwarehut.jpa.entityGraph.service; 2 | 3 | import com.softwarehut.jpa.entityGraph.model.Company; 4 | 5 | import org.springframework.dao.support.DataAccessUtils; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.persistence.EntityManager; 9 | import javax.persistence.PersistenceContext; 10 | import javax.persistence.Query; 11 | 12 | @Service(value = "companyServiceNamedQuery") 13 | public class CompanyServiceNamedQueryImpl implements CompanyService { 14 | 15 | @PersistenceContext 16 | private EntityManager entityManager; 17 | 18 | @Override 19 | public Company getCompanyWithDepartments(Long companyId) { 20 | Query query = entityManager.createNamedQuery("companyWithDepartmentsNamedQuery") 21 | .setParameter("id", companyId); 22 | 23 | return (Company) DataAccessUtils.singleResult(query.getResultList()); 24 | } 25 | 26 | @Override 27 | public Company getCompanyWithDepartmentsAndEmployees(Long companyId) { 28 | Query query = entityManager.createNamedQuery("companyWithDepartmentsAndEmployeesNamedQuery") 29 | .setParameter("id", companyId); 30 | 31 | return (Company) DataAccessUtils.singleResult(query.getResultList()); 32 | } 33 | 34 | @Override 35 | public Company getCompanyWithDepartmentsAndEmployeesAndOffices(Long companyId) { 36 | Query query = entityManager.createNamedQuery("companyWithDepartmentsAndEmployeesAndOfficesNamedQuery") 37 | .setParameter("id", companyId); 38 | 39 | return (Company) DataAccessUtils.singleResult(query.getResultList()); 40 | } 41 | 42 | @Override 43 | public Company getCompanyWithCars(Long companyId) { 44 | Query query = entityManager.createNamedQuery("companyWithCarsNamedQuery") 45 | .setParameter("id", companyId); 46 | 47 | return (Company) DataAccessUtils.singleResult(query.getResultList()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.h2.console.enabled=true 2 | spring.h2.console.path=/console/ 3 | logging.level.org.hibernate=debug 4 | spring.jpa.hibernate.ddl-auto=validate 5 | 6 | flyway.locations=db/migration/h2 -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V1__create_address.sql: -------------------------------------------------------------------------------- 1 | create table address (id bigint generated by default as identity, house_number varchar(255), street varchar(255), zip_code varchar(255), primary key (id)); -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V2__create_car.sql: -------------------------------------------------------------------------------- 1 | create table car (id bigint generated by default as identity, registration_number varchar(255), company_id bigint, primary key (id)); -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V3__create_company.sql: -------------------------------------------------------------------------------- 1 | create table company (id bigint generated by default as identity, name varchar(255), primary key (id)); 2 | 3 | alter table car add constraint FKjqp14dkmi2lh5kjavv4t0dkqy foreign key (company_id) references company; -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V4__create_department.sql: -------------------------------------------------------------------------------- 1 | create table department (id bigint generated by default as identity, name varchar(255), company_id bigint, primary key (id)); 2 | 3 | alter table department add constraint FKh1m88q0f7sc0mk76kju4kcn6f foreign key (company_id) references company; -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V5__create_employee.sql: -------------------------------------------------------------------------------- 1 | create table employee (id bigint generated by default as identity, name varchar(255), surname varchar(255), address_id bigint, department_id bigint, primary key (id)); 2 | 3 | alter table employee add constraint FKga73hdtpb67twlr9c1i337tyt foreign key (address_id) references address; 4 | alter table employee add constraint FKbejtwvg9bxus2mffsm3swj3u9 foreign key (department_id) references department; -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V6__insert_car.sql: -------------------------------------------------------------------------------- 1 | insert into company(id, name) values (1, 'Pepsi'); 2 | insert into company(id, name) values (2, 'Coca Cola'); 3 | insert into company(id, name) values (3, 'Sprite'); 4 | 5 | 6 | insert into car(id, registration_number, company_id) values (1, 'XYZ10ABC', 1); 7 | insert into car(id, registration_number, company_id) values (2, 'XYZ11ABC', 1); 8 | insert into car(id, registration_number, company_id) values (3, 'XYZ12ABC', 1); 9 | insert into car(id, registration_number, company_id) values (4, 'XYZ13ABC', 2); 10 | 11 | 12 | insert into address(id, house_number, street, zip_code) VALUES (1, 1, 'Street X', '12-341'); 13 | insert into address(id, house_number, street, zip_code) VALUES (2, 2, 'Street Y', '12-342'); 14 | insert into address(id, house_number, street, zip_code) VALUES (3, 3, 'Street Z', '12-343'); 15 | insert into address(id, house_number, street, zip_code) VALUES (4, 4, 'Street XX', '12-344'); 16 | insert into address(id, house_number, street, zip_code) VALUES (5, 5, 'Street YY', '12-345'); 17 | insert into address(id, house_number, street, zip_code) VALUES (6, 6, 'Street ZZ', '12-346'); 18 | insert into address(id, house_number, street, zip_code) VALUES (7, 7, 'Street XXX', '12-347'); 19 | 20 | insert into department(id, name, company_id) VALUES (1, 'Sales & Marketing', 1); 21 | insert into department(id, name, company_id) VALUES (2, 'Research & Development', 1); 22 | insert into department(id, name, company_id) VALUES (3, 'Administration', 1); 23 | insert into department(id, name, company_id) VALUES (4, 'Human Resources', 2); 24 | insert into department(id, name, company_id) VALUES (5, 'Sales & Marketing', 3); 25 | 26 | insert into employee(id, name, surname, address_id, department_id) VALUES (1, 'John', 'William', 1, 1); 27 | insert into employee(id, name, surname, address_id, department_id) VALUES (2, 'Robert', 'James', 2, 2); 28 | insert into employee(id, name, surname, address_id, department_id) VALUES (3, 'Donald', 'Tyler', 3, 3); 29 | -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V7__create_office.sql: -------------------------------------------------------------------------------- 1 | create table office (id bigint generated by default as identity, name varchar(255), address_id bigint, department_id bigint, primary key (id)); 2 | 3 | alter table office add constraint FKga73hdtpb67twlr9c35357tyt foreign key (address_id) references address; -------------------------------------------------------------------------------- /src/main/resources/db/migration/h2/V8__insert_office.sql: -------------------------------------------------------------------------------- 1 | insert into office(id, name, address_id, department_id) VALUES (1, 'Office of S&M Boston', 4, 1); 2 | insert into office(id, name, address_id, department_id) VALUES (2, 'Office of S&M New York', 5, 1); 3 | insert into office(id, name, address_id, department_id) VALUES (3, 'Office of R&D Boston', 6, 2); 4 | insert into office(id, name, address_id, department_id) VALUES (4, 'Office of A Los Angeles', 7, 3); --------------------------------------------------------------------------------