Transactionality
默认情况下,从 CrudRepository
继承的方法从 SimpleJpaRepository
继承事务配置。对于读取操作,事务配置 readOnly
标志被设置为 true
。所有其他内容都使用普通 @Transactional
进行配置,以便应用默认事务配置。受事务仓库片段支持的仓库方法从实际片段方法继承事务属性。
By default, methods inherited from CrudRepository
inherit the transactional configuration from SimpleJpaRepository
.
For read operations, the transaction configuration readOnly
flag is set to true
.
All others are configured with a plain @Transactional
so that default transaction configuration applies.
Repository methods that are backed by transactional repository fragments inherit the transactional attributes from the actual fragment method.
如果你需要调整存储库中声明的某个方法的事务配置,请在存储库接口中重新声明该方法,如下所示:
If you need to tweak transaction configuration for one of the methods declared in a repository, redeclare the method in your repository interface, as follows: .Custom transaction configuration for CRUD
public interface UserRepository extends CrudRepository<User, Long> {
@Override
@Transactional(timeout = 10)
public List<User> findAll();
// Further query method declarations
}
这样做会使 findAll()
方法在 10 秒内没有 readOnly
标志的情况下运行。
Doing so causes the findAll()
method to run with a timeout of 10 seconds and without the readOnly
flag.
更改事务行为的另一种方法是使用通常涵盖多个存储库的外观或服务实现。其目的是为非 CRUD 操作定义事务边界。以下示例展示了如何将此类外观用于多个存储库:
Another way to alter transactional behaviour is to use a facade or service implementation that (typically) covers more than one repository. Its purpose is to define transactional boundaries for non-CRUD operations. The following example shows how to use such a facade for more than one repository: .Using a facade to define transactions for multiple repository calls
@Service
public class UserManagementImpl implements UserManagement {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
public UserManagementImpl(UserRepository userRepository,
RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Transactional
public void addRoleToAllUsers(String roleName) {
Role role = roleRepository.findByName(roleName);
for (User user : userRepository.findAll()) {
user.addRole(role);
userRepository.save(user);
}
}
}
此示例会使对 addRoleToAllUsers(…)
的调用在事务内部运行(参与现有的事务或在不存在运行事务时创建一个新的事务)。然后忽略存储库中的事务配置,因为外部事务配置决定了实际使用的配置。请注意,你必须激活 <tx:annotation-driven />
或显式使用 @EnableTransactionManagement
才能使基于注释的外观配置生效。此示例假设你使用了组件扫描。
This example causes call to addRoleToAllUsers(…)
to run inside a transaction (participating in an existing one or creating a new one if none are already running). The transaction configuration at the repositories is then neglected, as the outer transaction configuration determines the actual one used. Note that you must activate <tx:annotation-driven />
or use @EnableTransactionManagement
explicitly to get annotation-based configuration of facades to work.
This example assumes you use component scanning.
请注意,从 JPA 的角度来看,对 save
的调用并不是绝对必要的,但为了保持与 Spring Data 提供的存储库抽象的一致性,仍然需要进行该调用。
Note that the call to save
is not strictly necessary from a JPA point of view, but should still be there in order to stay consistent to the repository abstraction offered by Spring Data.
Transactional query methods
默认情况下,声明的查询方法(包括默认方法)不会应用任何事务配置。要以事务方式运行这些方法,请在定义的存储库接口中使用 @Transactional
,如以下示例所示:
Declared query methods (including default methods) do not get any transaction configuration applied by default.
To run those methods transactionally, use @Transactional
at the repository interface you define, as shown in the following example:
@Transactional(readOnly = true)
interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
通常,你会希望 readOnly
标志设置为 true
,因为大多数查询方法仅读取数据。与此相反,deleteInactiveUsers()
使用了 @Modifying
注释并覆盖了事务配置。因此,该方法以 readOnly
标志设置为 false
的方式运行。
Typically, you want the readOnly
flag to be set to true
, as most of the query methods only read data. In contrast to that, deleteInactiveUsers()
makes use of the @Modifying
annotation and overrides the transaction configuration. Thus, the method runs with the readOnly
flag set to false
.
你可以将事务用于只读查询,并通过设置 You can use transactions for read-only queries and mark them as such by setting the |