为什么在Spring Data JPA中我必须使用@Modifying和@Transactional?
为什么在Spring Data JPA中我必须使用@Modifying和@Transactional?
在使用Query
注解(insert
,update
或delete
)在JpaRepository
中实现数据修改逻辑时,必须同时使用@Transactional
(不一定在存储库方法上)和@Modifying
。
我的理解如下。除非我们覆盖它们,否则JpaRepository
提供的所有CRUD操作都是事务性的。在实现存储库中的方法时,我们需要确保它仍然是事务性的。只需使用@Transactional
注解就可以实现。 readOnly
的默认值为false
,因此Spring “知道”它是一个修改查询。
问题是:那么为什么我们还需要@Modifying
注解(与@Transactional
一起)?也许我遗漏了什么?
我知道有类似这个或那个的讨论,但我缺少一个明确的解释,为什么如果@Transactional
携带了所有所需的信息,我们还必须使用@Modifying
。
在Spring Data JPA中,使用@Transactional注解可以将存储库实例上的CRUD方法设置为事务性操作。对于读操作,默认情况下,事务配置的readOnly标志设置为true,而对于其他操作,则使用普通事务配置。然而,@Modifying注解的出现是为了改变查询方法的执行方式。
@Modifying注解用于将查询方法视为修改查询,并改变其执行方式。此注解仅在通过@Query注解定义的查询方法上使用时才会生效,对于自定义实现方法或根据方法名称派生的查询方法,不需要使用此注解。需要@Modifying注解的查询包括INSERT、UPDATE、DELETE和DDL语句。
需要注意的是,@Modifying注解只在与@Transactional注解结合使用时才相关。不需要在@Transactional注解的方法上使用@Modifying注解,只要被@Modifying注解标记的方法在事务中执行即可。
根据文档中的描述,readOnly=true的事务可以调用被@Modifying注解标记的存储库方法,但只限于不支持只读事务的数据源。否则,执行将失败。这可能是因为某些数据库不支持只读事务,如H2数据库。
@Modifying注解的出现是为了将查询方法标记为修改查询,并改变其执行方式。在使用@Transactional注解时,如果需要执行修改操作,可以通过在查询方法上添加@Modifying注解来实现。