我一直试图找出这个显而易见的简单问题,但是我没有任何成功。 本质上,我的实体“工作”与实体“用户”具有一对一关系。
当尝试发布新的Job时,我不想发送有关User的所有信息,而只希望发送封装在Job内部的User对象中的userID。这是我的代码:
工作:
@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;
}
用户:
@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 ---------
}
控制器:
@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
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;
}
}
}
正如你们所看到的,JobService中有不同的方法。一个仅接收作业,其他仅接收作业和用户ID。 我的目标很容易:我发布了一个Job,并且想要正确接受用户通讯录的外键。不幸的是,使用2º方法,我遇到了这个问题:
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'}
]
这只是在发生,因为JCA试图将作业和用户插入DB。我只想插入作业,并引用用户的ID。
这是我的POST请求:
{
"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
}
}
如果有人对我的实施问题的解决方案有任何想法,那将非常有帮助,因为我为此花费了很多时间,但仍未找到好的解决方案。
谢谢
答案 0 :(得分:0)
此if语句不好,因为您的请求正文中没有id,因此它始终为null。
if (jobRepository.findById(job.getJobId()) == null) {
最好在JobRepository中创建一个新方法,例如:
Job findFirstByTitle(String title);
此职位归还职位。 但是主要问题是在ownerUserID字段中删除insertable = false。 所以这个必须是:
@JoinColumn(updatable = false)
private User ownerUserID;
因为如果保存作业对象,则应在该字段中插入参考。
答案 1 :(得分:0)
addJob
是否具有事务性?
如果没有,则在调用ownerUser
时jobRepository.save(job)
处于分离状态。这意味着JPA会尝试将其添加为新用户。添加@Transactional
应该可以解决此问题。
顺便说一句,如果您不打算同时更新User
及其Job
,那么您可能不希望cascade = ALL
上的Job.ownerUserID