我在Spring Data JPA和Hibernate中有项目。
有两个JPA实体 - 用户和工作。每个用户都有多个作业。每个作业都有字段状态。创建新作业时,会向远程服务器发送新请求,并以状态IN PROGRESS保存作业。
可以使用它的ID从远程服务器查询更新的状态。请求的业务逻辑应该始终返回存储的状态,但是当作业处于IN PROGRESS状态时,应该查询远程服务器的更新状态,该状态应该在之后存储。
应该解释我的意图的伪代码:
@Entity
class User {
private long id;
private String username;
private Collection<Jobs> jobs;
}
@Entity
class Job {
private long id;
private User user;
private Status status;
@Inject
private JobRepository jobRepository;
@PrePersist
private setDefaultStatus() {
status = IN_PROGESS;
}
@PostLoad
private checkUpdatedStatus() {
if (this.status == IN_PROGESS) {
this.status = askRemoteServerForJobStatus(this.id);
jobRepository.save(this);
}
}
}
伪代码用法:
userRepsitory.find(1).jobs // should trigger checkUpdatedStatus
jobsRepository.findAll() // should trigger checkUpdatedStatus
我认为在Job实体中包含jobRepository依赖项是一个好习惯(如伪代码所示),所以我当前的实现在存储库中完成所有这些 - 我有findAll()这样的方法这将调用PostLoad / checkUpdatedStatus类方法。但是我也从所有其他存储库中调用它,例如User repository,它也可以获取Job项。
在我看来,这是一个非常合理的用例,所以我不相信,没有更好的方法可以做到这一点。有没有人做过类似的事情?如果你能让我走上正轨,我会非常高兴。
谢谢你, vlastikcz
答案 0 :(得分:2)
将存储库注入实体并不是一个好的举措。实体是持久化结构,存储库应该管理实体而不是相反。考虑事务划分和瞬态/分离实例。
添加实体时,有一种更好的方法可以调用某个登录。您可以使用电子邮件vent listener for this。您配置一个也是Spring bean的加载侦听器,因此您可以在此侦听器中注入其他服务/存储库。
答案 1 :(得分:0)
最后,@ Alan的评论让我再次思考,我提出了不同的方法。
创建作业后,我启动一个异步任务,只需轮询远程服务器,直到收到结果。
像这样:
@HandleAfterCreate
public void addNewRemoteJob(Job job) {
remoteJobDispatcher.sendRequest(job);
remoteJobDispatcher.waitForTheResult(job);
}
class RemoteJobDispatcher {
@Async
public void waitForTheResult(Job job) {
while(true) {
status = askRemoteServerForJobStatus(job)
if (status != IN_PROGRESS) {
job.setStatus(status);
jobRepository.save(job);
return;
}
sleep(2000);
}
}
}
可能有类似的计划或启动作业,以处理可能的意外应用程序状态,但没关系。
谢谢!