Java 包含多个操作和回滚的Spring事务
我必须编写一些方法将值更改为数据库,并在文件系统上进行一些操作。 因此,我必须进行以下步骤:Java 包含多个操作和回滚的Spring事务,java,mysql,spring,transactions,rollback,Java,Mysql,Spring,Transactions,Rollback,我必须编写一些方法将值更改为数据库,并在文件系统上进行一些操作。 因此,我必须进行以下步骤: 将布尔值更新字段设置为真到数据库中。它用于避免访问与此值链接的文件系统和数据库信息(例如车队) 对数据库进行一些操作。例如,更改日期、名称、值或其他字段。这些更改会影响更多的数据库表 对文件系统和数据库进行更改 将布尔值更新设置为false 可以想象,我必须管理错误并启动回滚过程来恢复数据库和文件系统。 我对如何编写我的方法有些怀疑。我有: 实体 扩展了JpaRepository的存储库接口,并具有从
更新
字段设置为真
到数据库中。它用于避免访问与此值链接的文件系统和数据库信息(例如车队)更新设置为false
- 实体
- 扩展了
的存储库接口,并具有从方法名称创建的查询和JpaRepository
注释的@Query
(否则我收到错误)@Transactional
- 服务接口
- 包含对数据库进行简单更改的所有方法的服务实现。此类用
@Transactional
@Transactional(rollbackFor=FileSystemException.class)
private void changeDisplacement(int idApplication, int idDisplacement){
applicationServices.setUpdating(true); //this has be to write immediatly into database so that the other methods can stop using this application
Application application = applicationServices.getId(idApplication);
application.setDisplacement(displacementServices.getId(idDisplacement));
//OTHER OPERATIONS ON DIFFERENT TABLES
//OPERATIONS ON FILE SYSTEM CATCHING ALL EXCEPTION WITH TRY-CATCH AND IN THE CATCH RESTORE FILESYSTEM AND THROW FileSystemException to start database rollback
//In the finally clause use applicationServices.setUpdating(false)
}
它是否可以使用此逻辑,或者此处的@Transactional
字段错误?
谢谢这里有多个问题,有些问题很难理解,这里有一些输入。当你有这个:
@Transactional(rollbackFor=FileSystemException.class)
private void changeDisplacement(int idApplication, int idDisplacement){
applicationServices.setUpdating(true);
只有当@Transactional
完成时,该标志才会命中数据库。更改将保留在hibernate上下文中,直到@Transactionl
方法结束
因此,当您执行changeplacement
而其他人来读取该标志时,它将看到false(因为您还没有将其写入数据库)。您可以通过READ_UNCOMMITTED
获得它,但如果您允许,则由您的应用程序决定
您可以使用REQUIRES_NEW
的方法,并在那里将该标志设置为true,如果要恢复,请将该标志重新更新
通常,更新数据库和文件系统并不容易(保持同步)。我以前做过的方法(可能是更好的选择)是注册事件(一旦创建了正确的数据库),然后写入文件系统 这里有多个问题,有些问题很难理解,这里有一些输入。当你有这个:
@Transactional(rollbackFor=FileSystemException.class)
private void changeDisplacement(int idApplication, int idDisplacement){
applicationServices.setUpdating(true);
只有当@Transactional
完成时,该标志才会命中数据库。更改将保留在hibernate上下文中,直到@Transactionl
方法结束
因此,当您执行changeplacement
而其他人来读取该标志时,它将看到false(因为您还没有将其写入数据库)。您可以通过READ_UNCOMMITTED
获得它,但如果您允许,则由您的应用程序决定
您可以使用REQUIRES_NEW
的方法,并在那里将该标志设置为true,如果要恢复,请将该标志重新更新
通常,更新数据库和文件系统并不容易(保持同步)。我以前做过的方法(可能是更好的选择)是注册事件(一旦创建了正确的数据库),然后写入文件系统
@Transactional
在这里可以。唯一的问题是您需要设置应用程序服务的传播。setUpdating
到需要\u NEW
以便单独提交:
public class ApplicationServices {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void setUpdating(boolean b) {
// update DB here
}
}
在异常情况下,只要您在finally块中调用了
setUpdating
,它仍然会更新数据库。@Transactional
在这里是可以的。唯一的问题是您需要设置应用程序服务的传播。setUpdating
到需要\u NEW
以便单独提交:
public class ApplicationServices {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void setUpdating(boolean b) {
// update DB here
}
}
在异常的情况下,只要您在finally块中调用
setUpdating
,它仍然会更新数据库。我认为您无法保证文件还原阶段,如果在写入文件时抛出异常,则很可能再次写入,以还原其状态,也会失败。当然,我将尝试只更新一次,如果还原失败,我会发送电子邮件并保持文件系统锁定,直到手动操作解决问题。我认为您无法保证文件还原阶段,如果在写入文件时引发异常,则很可能再次写入,以恢复其状态,也会失败。确定,我将尝试只更新一次,如果还原失败,我将发送电子邮件并保持文件系统锁定,直到手动操作解决问题。谢谢,此批注创建了一个新事务,暂时停止主事务,对吗?因此,如果使用@Transactional
注释的方法调用具有相同注释的其他方法,则只在主注释的和处写入数据库中的值?setUpdating
方法使用新的TX,而不依赖调用方方法的事务。如果操作成功,它将提交,其他TX将看到data.perfect,问题的第二部分是我是怎么想的?如果第二部分是指回滚文件系统,那么您必须自己做。Spring事务对您执行的文件系统操作没有任何线索。OIC,是的,如果您不指定传播,它们都共享相同的TX,并且在最外层的方法完成后TX被提交。谢谢,