Spring Data Repository Save - 如何知道它的数据真的得到了保存?

时间:2018-05-16 07:29:03

标签: hibernate spring-boot spring-data-jpa

将数据保存到数据库时,我真的想知道保存的数据。但我的spring应用程序似乎没有抛出错误/异常。

所以我所做的就是在保存操作myRepository.save(entity)之前在我的应用程序中设置一个断点。当它在断点处停止时,我停止了我的数据库服务,然后继续保存。

我没有例外,save()返回的保存实体看起来很好。但是DB中没有保存任何东西。我甚至可以myRepository.findOne(id),它会找到实体。我怎么知道它真的得救了?

如果数据库在我的@Transactional方法之前出现故障,那么我会收到错误,但不会在方法中间停止。

3 个答案:

答案 0 :(得分:1)

所有这些操作都将在内存中完成,直到调用commit。提交后,它将持久保存到相应的dbs中。在提交之后,db将调用与db相关的触发器,例如foriegn key / related stuffs,如果出现错误,则抛出其他存储库将简单地返回实体对象。

答案 1 :(得分:1)

repository.save()不一定会刷新对数据库的更改。它只会在以下情况下这样做:

  • 达到了交易的结束(= @Transactional方法的结束)
  • 取决于来电(例如,当您开始使用repository.findAll()repository.findOne(id)时)
  • ...

Hibernate documentation以及交易后写中提到了这一点:

  

要减少数据库中的锁争用,物理数据库事务需要尽可能短。长数据库事务会阻止您的应用程序扩展到高度并发的负载。不要在最终用户级工作期间打开数据库事务,而是在最终用户级工作完成后打开它。这个概念被称为事务性后写。

这意味着如果您的数据库在刷新更改时正在关闭,那么您实际上应该得到一个例外。但是,这可能发生在方法结束时,在其他地方,......。

这也是为什么有时难以追踪异常发生原因的原因,因为冲洗可能比代码中实际保存发生的时间要晚得多。

如果您使用repository.flush()repository.saveAndFlush()方法,您可以在必要时手动刷新到数据库,但通常您不应该这样做。

答案 2 :(得分:1)

解决方案是将我的数据库调用myRepository.save(entity)包装在服务类或使用@Transactional注释的单独方法中。

这种方式调用方法时,@Transactional,我会抛出一个异常。由于提交是在调用方法之后完成的。感谢您Maria Sekar的见解。之前我在Controller上有@Transactional注释,这给了我一个错误,但我没有机会对它做任何事情。

所以解决方案,简化

在Controller类中

@RequestMapping(value = "/notification", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Notification saveNotification(@RequestBody Notification notification) {
    Notification savedNotification = null;
    try {
        myService.save(notification);
    } catch (SQLServerException e) {
        throw new CouldNotSaveNotification(e);
    }
    return savedNotification;
}

在服务类

@Transactional
public save(Notification notification) {
    myRepo.save(notification);
}