I have two spring entities, job and employer, which have a bidirectional association.
Job Entity
@Entity
@Table(name = "job")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Job {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "job_id", nullable = false)
private Integer id;
@Column(name = "title", nullable = false)
private String title;
@ManyToOne(optional = false)
@JoinColumn(name = "employer_employer_id", nullable = false)
@JsonBackReference
private Employer employer;
}
Employer Entity
@Entity
@Table(name = "employer")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Employer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employer_id", nullable = false)
private Integer employerId;
@Column(name = "name", nullable = false)
private String name;
//Mapped by indicates the inverse side of the relationship.
@OneToMany(mappedBy = "employer", orphanRemoval = true)
@JsonManagedReference
private List<Job> jobs = new ArrayList<>();
}
I also have two simple CRUD repositories
Let's say that I have an existing employer object saved in the database. In my jobs service, I want to have a method that creates a new job. My question is, what is the correct Spring boot way to save a new job entry in the database where the employee id foreign key relates back to that existing job in the database.
Here is my first attempt, and it works, however it doesn't seem very efficient. Why should I have to retrieve the entire employer object from the database, when I really just want to specify the employer ID of the job I am trying to save? Is there a way I can avoid making this extra database call, and when we are saving the job to the database, just easily specify an existing employer ID on that new job we are saving to the database? Or is it Spring best practice to have to save the entire employee object here, even if it already exists?
Employer e = employerRepository.findById(0).orElseThrow(IllegalArgumentException::new);
job1.setEmployer(e);
jobRepository.save(job1);
CodePudding user response:
Best way is use getOne so you don't even have to fetch the empoyer
Employer e = employerRepository.getOne(id);
job1.setEmployer(e);
jobRepository.save(job1);
If employer does t exist an exception will be thrown when you save job.
getOne is deprecated in later versions of jpa so use this instead
JpaRepository#getReferenceById(ID)
CodePudding user response:
Good/progressive question:
Why should I have to retrieve the entire employer object from the database, when I really just want to specify the employer ID of the job I am trying to save?
We don't have to! We can:
Employer empler =
entityManager.getRefernce(Employer.class, 0L);
Resp. with spring-data:
JPARepository.getReferenceByIdID(...);
Regarding "how to do it best" (and in which queries it results), i can additionally very recommend:
https://vladmihalcea.com/the-best-way-to-map-a-onetomany-association-with-jpa-and-hibernate/
(Where Employer
is analogous to Post
and Job
analogous to PostComment
;)