I've been trying to figure out this apparent easy issue, but I'm having no sucess in it. In essence, My entity "Job" has a One To One Relation with entity "User".
When trying to post a new Job, I do not want to send all the info regarding the User, but only the userID encapsulated in the User object inside Job. Here is my code:
Job:
@Entity
@Table(name="TB_Job")
public class Job implements Serializable {
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Id long jobId;
private String title, description, location;
private boolean job_assigned, time_to_assigned, job_active;
Date createDate;
Time licitationTime;
private int stateId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(insertable = false, updatable = false)
private User ownerUserID;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn()
private User assignedUserID;
private int categoryID;
}
User:
@Entity
@Table(name = "TB_User")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "user_id")
private long userId;
@Column(name = "email", nullable = false, unique = true)
@Email(message = "*Please provide a valid Email")
@NotEmpty(message = "*Please provide an email")
private String email;
@Column(name = "password")
@Length(min = 5, message = "*Your password must have at least 5 characters")
@NotEmpty(message = "*Please provide your password")
private String password;
@NotEmpty(message = "*Please provide your name")
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
@NotEmpty(message = "*Please provide your last name")
private String lastName;
@Column(name = "active")
private int active;
@Column(name = "city")
@NotEmpty(message = "*Please provide your City name")
private String city;
// --------- FOREIGN KEYS ---------
// Column used to FK in AssocUserRole
@OneToOne(mappedBy = "user")
private AssocUserRole user;
// Column used to FK in Job
@OneToMany(mappedBy = "ownerUserID")
private Set<Job> ownerUserID;
// Column used to FK in Job
@OneToMany(mappedBy = "assignedUserID")
private Set<Job> assignedUserID;
// --------- FOREIGN KEYS ---------
}
Controller:
@RestController
@RequestMapping(path = "/api")
public class JobController {
@Autowired
private JobRepository jobRepository;
@Autowired
private JobService jobservice;
@PostMapping("/job/{ownerId}")
public Job createJob(@RequestBody Job job, @PathVariable(value = "ownerId") long ownerId) {
return jobservice.addJob(job, ownerId);
}
@PostMapping("/job")
public Job createJob(@RequestBody Job job) {
return jobservice.addJob(job);
}
}
Service:
@Service
public class JobService {
@Autowired
JobRepository jobRepository;
@Autowired
UserRepository userRepository;
public Job addJob(Job job, long ownerId) {
try {
// Checks if owner actually exists
User ownerUser = userRepository.findById(ownerId);
// If it does
if(ownerUser != null) {
// Checks if job does not exists already
if (jobRepository.findById(job.getJobId()) == null) {
// Gets and Sets Job Owner FK to Job
job.setOwnerUserID(ownerUser);
return jobRepository.save(job);
} else {
return null;
}
}
else{
return null;
}
} catch (Exception Ex) {
return null;
}
}
public Job addJob(Job job) {
try {
// Checks if job does not exists already
if (jobRepository.findById(job.getJobId()) == null) {
// Gets and Sets Job Owner FK to Job
//job.setOwnerUserID(ownerUser);
return jobRepository.save(job);
} else {
return null;
}
} catch (Exception Ex) {
return null;
}
}
}
As you guys can see, I have different methods in JobService. One recieves only the Job, other the Job and the userID. My objective is quite easy: I post an Job, and I want to properly accept the Foreign key to the User correspondent. Unfortunally, using the 2º method, I am having this issue:
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
Validation failed for classes [com.homelancer.models.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='*Please provide your password', propertyPath=password, rootBeanClass=class com.homelancer.models.User, messageTemplate='*Please provide your password'}
ConstraintViolationImpl{interpolatedMessage='*Please provide your last name', propertyPath=lastName, rootBeanClass=class com.homelancer.models.User, messageTemplate='*Please provide your last name'}
ConstraintViolationImpl{interpolatedMessage='*Please provide an email', propertyPath=email, rootBeanClass=class com.homelancer.models.User, messageTemplate='*Please provide an email'}
ConstraintViolationImpl{interpolatedMessage='*Please provide your name', propertyPath=firstName, rootBeanClass=class com.homelancer.models.User, messageTemplate='*Please provide your name'}
ConstraintViolationImpl{interpolatedMessage='*Please provide your City name', propertyPath=city, rootBeanClass=class com.homelancer.models.User, messageTemplate='*Please provide your City name'}
]
This is only happenning, because JCA is trying to insert in DB the Job AND the User. I do only want to get the Job inserted, and the ID from the user referenced.
This is my POST request :
{
"category": "batatas",
"categoryID": 0,
"createDate": "2019-12-29T21:50:42.847Z",
"description": "teste bc",
"job_active": true,
"job_assigned": true,
"location": "povoa city",
"stateID": 1,
"time_to_assigned": true,
"title": "granda job",
"ownerUserID": {
"userId": 116
}
}
If anyone has any ideia about a solution to my implementation issue it would be very helpful, since I lost quite a few hours around this and have yet not found and good solution.
Thanks