【问题标题】:Do we need both @Transactional and @Modifying annotation in Spring?我们在 Spring 中需要 @Transactional 和 @Modifying 注解吗?
【发布时间】:2018-06-27 02:57:10
【问题描述】:

我仍在尝试了解 @Transactional 的工作原理。

我在 Service 类的方法上有 @Transactional 注释,在 Repository 类的方法上有 @Modifying 注释。 @Transactional注解的方法是否适用于Repository中注解@Modifying的方法?

我的理解:

@Transactional 在具有@Transactional( readOnly = true ) 的类的方法上不会将数据写入数据库,而在使用@Transactional 时,会将数据写入数据库。

修改查询

  1. 修改方法签名只能返回voidIntegerint
  2. 更新查询必须是事务性的,用@Transactional标记
  3. Spring Data 将删除 EntityManager 中的所有未刷新更改,更改为 @Modifying(clearAutomatically=false)

正如第二点所说,@Modifying 查询必须有@Transactional(readOnly=false),所以我们可以在@Service 级别的方法调用或@Repository 方法级别的调用中添加它。如果在@Service 级别添加,它也适用于从@Service 级别方法调用中调用的@Respository 方法?

例子:

@Service
class AnimalServiceImpl implements AnimalService {

@Autowire
AnimalRepository animalRepository;

@Override
@Transactional
public void persistAnimal() {
....
animalRepository.save();
}

@Override
@Transactional(readOnly = true)
public void checkIfAnimalPresent() {

...
animalRepository.checkIfPresent();

}

@Override
@Transactional
public void deleteAnimal() {
...
animalRepository.deleteAnimal();
}
}

存储库

@Repository
@Transactional(readOnly=true)
public interface AnimalRepository extends org.springframework.data.repository.Repository {

@Modifying
@Query(...)
void save();

@Modifying
@Query(...)
int checkIfPresent() 

@Modifing
@Query(..)
int deleteAnimal();
}

我的问题是:

  1. 当我们在存储库@Repository 级别拥有@Transactional 而我在方法上有@Modifying 时,为什么我们需要在服务类中使用@Transactional 修改实体并将其写入数据库(仅因为我在类级别有@Transactional(readOnly = true))?
  2. Service 类上的注解 @Transactional 是否会传播到 @Repository 类?

我希望我对这里的问题和示例非常清楚。

【问题讨论】:

  • 你不是很清楚(恕我直言)。是的,即使使用 @Modifying 修改数据时,您也需要 @Transactional,这只是一个注释,让 Spring Data 知道您有一个 @Query 可以更改内容。 @Transactional 标记事务的开始和结束。如果你把它放在你的服务层中,从一个方法中调用的所有东西都参与了同一个事务。如果你不该单个方法中的每个调用都将成为它自己的事务。
  • 感谢您的澄清。我有最后一个问题,我已经在存储库级别有事务注释(但是 readOnly=true)。当我修改我的查询并且我在服务级别没有事务但我在存储库级别有一个 readOnly = true 时会发生什么,实体会在数据库中写入/更新吗?当我不小心忘记使用事务注释来注释服务级别方法时,它以某种方式对我有用。我是 string、jpa 和 hibernate 的新手,所以请耐心等待。:)

标签: java spring transactions spring-transactions


【解决方案1】:

@Transactional 的工作原理如下:

默认情况下,存储库实例上的 CRUD 方法是事务性的。
对于读操作,事务配置readOnly标志设置为true
所有其他人都使用普通的@Transactional 进行配置,以便应用默认事务配置。
如果您需要调整存储库中声明的方法之一的事务配置,您可以覆盖该方法并添加带有所需属性值的 @Transactional 注释。

另一种改变事务行为的方法是使用(通常)覆盖多个存储库的外观或服务实现。
其目的是为非 CRUD 操作定义事务边界。

如果您使用这种方法,那么存储库中的事务配置将被忽略,因为外部事务(在服务层中定义)配置决定了实际使用的事务。

参考:Spring Data JPA - Reference Documentation - 5.7. Transactionality

【讨论】:

    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 2021-01-22
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多