JPA and Hibernate persisting @manytoOne relationship

1.4k Views Asked by At

I have this situation:

@Entity
@Table(name = "project_leader")
public class ProjectLeader {

@ManyToOne
@JoinColumn(name = "projectId")
@JsonBackReference(value = "project")
private Project project;

...

and related entity

@Entity
@Table(name = "project")
public class Project {

@OneToMany(fetch = FetchType.EAGER, mappedBy = "project", orphanRemoval = true)
@Cascade(CascadeType.ALL)
@JsonManagedReference(value = "project")
private Set<ProjectLeader> projectLeaders = new HashSet<ProjectLeader>();

In situation for example

Project_A with ProjectLeader_1 and Project_B with ProjectLeader_2

and when I try to add ProjectLeader_1 to Project_B also I get ProjectLeader_1 completely moved from Project_A to Project_B, so I have a following situation:

Project_A with -No leader- and Project_B with ProjectLeader_2 ProjectLeader_1

The desirable result should be:

Project_A with ProjectLeader_1 and Project_B with ProjectLeader_2 ProjectLeader_1

Here is the method used for assigning leaders to project:

private Project initializeProject(@Nonnull ProjectDto projectDto) {
        Project project = null;
        if (projectDto.getId() != null) {
            project = projectRepository.findOne(projectDto.getId());
        } else {
            project = new Project();
        }
        project.setName(projectDto.getName());
        project.setProjectType(projectDto.getProjectType());
        project.setFinancedBy(projectDto.getFinancedBy());

        Set<ProjectLeader> projectLeaders = new HashSet<ProjectLeader>();

        for (ProjectLeaderDto projectLeaderDto : projectDto.getProjectLeaderDtos()) {
            ProjectLeader projectLeader = new ProjectLeader();
            Professor professor = null;
            if (projectLeaderDto.getId() != null && projectLeaderDto.getId() > 0L) {
                projectLeader = projectLeaderRepository.findOne(projectLeaderDto.getId());
            }
            if (projectLeaderDto.getProfessorId() != null && projectLeaderDto.getProfessorId() > 0L) {
                professor = professorRepository.findOne(projectLeaderDto.getProfessorId());
            }
            projectLeader.setName(projectLeaderDto.getName());
            projectLeader.setSurname(projectLeaderDto.getSurname());
            projectLeader.setProject(project);
            projectLeader.setProfessor(professor);

            projectLeaders.add(projectLeader);
        }
        // If collection from Dto miss some element from original collection, we
        // remove it from original
        Iterator<ProjectLeader> currentLeadersIterator = project.getProjectLeaders().iterator();
        while (currentLeadersIterator.hasNext()) {
            ProjectLeader projectLeader = currentLeadersIterator.next();
            if (!projectLeaders.contains(projectLeader)) {
                currentLeadersIterator.remove();
                projectLeader.setProject(null);
            }
        }
        // If original collection miss some element from Dto collection, we add
        // it to original
        Iterator<ProjectLeader> newLeadersIterator = projectLeaders.iterator();
        while (newLeadersIterator.hasNext()) {
            ProjectLeader projectLeader = newLeadersIterator.next();
            if (!project.getProjectLeaders().contains(projectLeader)) {
                project.getProjectLeaders().add(projectLeader);
                projectLeader.setProject(project);
            }
        }

        return project;
    }

What can be potential reason for this?

I'm new here so please post me a link if there is similar question elsewhere. Thank you.

1

There are 1 best solutions below

1
On BEST ANSWER

I think there is an issue in inserting, please note each project has one project leader, so if you put another leader to project, the old one will be deleted and new one will be inserted, I wrote small program about your issue:

package leader;

import java.io.Serializable;
import javax.persistence.*;


/**
 * The persistent class for the Project database table.
* 
*/
@Entity
@NamedQuery(name="Project.findAll", query="SELECT p FROM Project p")
public class Project implements Serializable {
private static final long serialVersionUID = 1L;

@Id
private int id;

//bi-directional many-to-one association to ProjectLeader
@ManyToOne
@JoinColumn(name="Leader_Id")
private ProjectLeader projectLeader;

public Project() {
}

public int getId() {
    return this.id;
}

public void setId(int id) {
    this.id = id;
}

public ProjectLeader getProjectLeader() {
    return this.projectLeader;
}

public void setProjectLeader(ProjectLeader projectLeader) {
    this.projectLeader = projectLeader;
}

}

ProjectLeader class:

package leader;

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;



@Entity
@NamedQuery(name="ProjectLeader.findAll", query="SELECT p FROM ProjectLeader p")
 public class ProjectLeader implements Serializable {
 private static final long serialVersionUID = 1L;

@Id
private int id;

//bi-directional many-to-one association to Project
@OneToMany(mappedBy="projectLeader",fetch=FetchType.EAGER,orphanRemoval=true)
private List<Project> projects;

public ProjectLeader() {
}

public int getId() {
    return this.id;
}

public void setId(int id) {
    this.id = id;
}

public List<Project> getProjects() {
    return this.projects;
}

public void setProjects(List<Project> projects) {
    this.projects = projects;
}

public Project addProject(Project project) {
    getProjects().add(project);
    project.setProjectLeader(this);

    return project;
}

public Project removeProject(Project project) {
    getProjects().remove(project);
    project.setProjectLeader(null);

    return project;
}

}

and Test class

package leader;

 import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.PersistenceUnit;

public class Test {

@PersistenceUnit(unitName="leader")
EntityManagerFactory emf1;


  public static void main(String[] args) {
    Project projectA = new Project();
    projectA.setId(1);


    Project projectB = new Project();
    projectB.setId(2);


    ProjectLeader leaderA = new ProjectLeader();
    leaderA.setId(1);

    ProjectLeader leaderB = new ProjectLeader();
    leaderB.setId(2);



    EntityManagerFactory emf =    Persistence.createEntityManagerFactory("leader");
    EntityManager em=emf.createEntityManager();
    em.getTransaction().begin();
    em.persist(leaderA);
    em.persist(leaderB);

   // projectA.setProjectLeader(leaderA);
    projectA.setProjectLeader(leaderB);

    projectB.setProjectLeader(leaderA);
   // projectB.setProjectLeader(leaderB);


    em.persist(projectA);
    em.persist(projectB);
    em.getTransaction().commit();



  }

}