【问题标题】:Spring Hibernate @Transactional clarificationsSpring Hibernate @Transactional 澄清
【发布时间】:2019-07-10 16:50:07
【问题描述】:

我对@Transactional 注释有很多困惑。

1) 如果我只使用声明性方法,是否足以将我的服务类/方法标记为 @Transactional,或者我应该创建配置 bean 和属性,如 Baeldung article 所示?

2) 在某些情况下,我甚至需要使用编程方法,以便能够在工作流程的特定点显式调用 flush()。在这种情况下,以前的休眠配置定义是强制性的吗?

【问题讨论】:

  • @Transactional 确保您的方法封装在事务中。有时,您必须在事务中间调用 flush 来“更新”数据库的状态,例如当您从数据库中删除内容然后尝试从中选择时。删除后不刷新,您的选择可能无法正常工作。
  • @NathanHughes 考虑到配置中的信息非常通用,我希望 Hibernate 能够“猜测”它们,即读取其中许多设置已经指定的 application.properties。如果第一个答案不是“是”,那么第二个问题就会有意义,就像看起来那样。 ayrton 我的交易包含一个 cicle,在其中每次迭代都调用对上一次迭代引用的实体的引用。然后我必须显式调用flush(),否则在第二次迭代中Spring会抱怨第一个的引用仍然是瞬态的。
  • @NathanHughes 在提交之前,PlatformTransactionManager 会要求 Hibernate 刷新会话。

标签: java spring hibernate spring-boot transactional


【解决方案1】:

如果您在 Spring Boot 项目中,则不需要显式声明 SessionFactoryPlatformTransactionManager Bean。它们将为您自动配置。

是的,将Transactional 注释放在您的类或方法上就足以让事务发生。自动提交甚至应该被自动关闭(出于优化目的),以防它没有在 DataSource 级别完成。

对于“程序化”部分,您应该考虑留在注释方面。您可以使用事务传播策略来隔离某些操作。


关于使用声明式注释方法的几个重要说明。

如果可能,请记住注释 public 方法。任何其他方法的可见性都无法通过 Java 代理或 CGLIB 代理进行管理,因此,即使您不会注意到,这些方法也不会参与事务上下文。对于protectedprivate 方法,您必须使用AspectJ。

还请记住,在使用代理时,自调用(并期待新事务)不起作用。


要使用程序化方法,您只需 Autowire TransactionTemplatePlatformTransactionManager Bean。

PlatformTransactionManager 允许对事务进行更多自定义,而TransactionTemplate 更像是一个实用程序对象(但可以根据需要对其进行建模)。

显然,不要在同一个方法调用堆栈中混合使用这两种方法。

【讨论】:

  • 是的,我忘了说我正在使用 Spring Boot。就我而言,我怀疑我是否可以通过传播策略解决我的问题,我可以访问自动配置的会话吗?
  • 当您说“不要混合使用两种方法”时,您的意思是我不应该从声明性方法中调用编程方法吗?
  • @4javier 是的,不要在 Transactional 注释方法中显式使用 TransactionManager。虽然它可以工作并且您可以进行嵌套事务,但对于您和未来的维护者来说,它会变得令人困惑。
  • 嗯,这有点问题。我选择了一种个人的方法,其中一个方法发出一个事务,级联可以调用另一个事务等等......我认为我应该重写我的代码以原子化每个事务并存储返回的ID,以便能够通过它到下一个在单独的方法中调用。
猜你喜欢
  • 1970-01-01
  • 2012-10-15
  • 2011-03-22
  • 2017-02-23
  • 2017-12-10
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 2011-07-19
相关资源
最近更新 更多