Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA one to many relationship query

Implemented one to many relationship and it is working fine.

My issue is when i run the below query, if the table has 100 employee rows, and each employee has 2 departments. The database query is called 101 times, because for each employee it is calling department query, it is taking very long to complete calling all hundred rows, can any one suggest any alternative solution?

Please see the details below

Queries it is calling:

    First query is :    SELECT * FROM Employee e

    Next 100 queries : SELECT * FROM DEPARTMENT d WHERE d.EmployeeId=?

JPA Database call :

    javax.persistence.Query query = em.createNamedQuery("SELECT * FROM Employee e", Employee.class);

    return query.getResultList();




    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.Id;
    import javax.persistence.NamedNativeQueries;
    import javax.persistence.NamedNativeQuery;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    @Entity
    @Table(name = "EMPLOYEE")
    public class Employee implements Serializable
    {
        @Id
        @Column(name = "EmployeeId")
        String employeeId;

        @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        private List<Department> departments;

        public List<Department> getDepartments() {
            return departments;
        }

        public void setDepartments(List<Department> departments) {
            this.departments = departments;
        }

        public String getEmployeeId() {
            return employeeId;
        }

        public void setEmployeeId(String employeeId) {
            this.employeeId = employeeId;
        }
    }

    @Entity
    @Table(name = "DEPARTMENT")
    public class Department implements Serializable
    {
        private static final long serialVersionUID = 1L;

        @Id
        @Column(name = "DepartmentID")
        String departmentId;

        @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "EmployeeId", insertable = false, updatable = false)
        private Employee employee;
    }

The output xml:

        <Employees>
            <Employee>
                <name>Rob</name>
                <Departments>
                    <Departmnet><id>1</id></Departmnet>
                    <Departmnet><id>2</id></Departmnet>
                </Departments>  
            </Employee>
            <Employee>
                <name>Sam</name>
                <Departments>
                    <Departmnet><id>1</id></Departmnet>
                    <Departmnet><id>2</id></Departmnet>
                </Departments>  
            </Employee>
        </Employees>
like image 857
user3157090 Avatar asked Mar 06 '14 10:03

user3157090


People also ask

How do you write one to many relationship in JPA?

A one-to-many relationship between two entities is defined by using the @OneToMany annotation in Spring Data JPA. It declares the mappedBy element to indicate the entity that owns the bidirectional relationship.

How fetch data in many-to-many relationship in JPA?

In JPA we use the @ManyToMany annotation to model many-to-many relationships. This type of relationship can be unidirectional or bidirectional: In a unidirectional relationship only one entity in the relationship points the other. In a bidirectional relationship both entities point to each other.

How do you fetch a one to many DTO projection with JPA and hibernate?

Fetching a one-to-many DTO projection with JPA and Hibernate. The postDTOMap is where we are going to store all PostDTO entities that, in the end, will be returned by the query execution. The reason we are using the postDTOMap is that the parent rows are duplicated in the SQL query result set for each child record.


2 Answers

This is a typical N+1 selects issue. I usually solve this with JOIN FETCH queries as described here and here

like image 115
Tasos P. Avatar answered Sep 26 '22 05:09

Tasos P.


You could switch the fetchtype to lazy, which will cause the departments only to be queried when necessary.

@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Department> departments;
like image 45
Kevin Bowersox Avatar answered Sep 26 '22 05:09

Kevin Bowersox